{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b2d06c70",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入必要的库\n",
    "import os\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.optim as optim\n",
    "import torch.nn.functional as F\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "from tqdm import tqdm\n",
    "from datetime import datetime\n",
    "from PIL import Image\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "import random\n",
    "from torchvision import transforms, datasets\n",
    "from torch.nn import init\n",
    "import warnings\n",
    "import cv2\n",
    "from torchmetrics.image.inception import InceptionScore\n",
    "from torchmetrics.image.fid import FrechetInceptionDistance\n",
    "from torchdiffeq import odeint\n",
    "\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "# 设置中文字体\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']\n",
    "plt.rcParams['axes.unicode_minus'] = False"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5023955c",
   "metadata": {},
   "source": [
    "## 1.参数设置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "90002f6f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用设备: cuda\n",
      "GPU设备: NVIDIA GeForce RTX 4060 Laptop GPU\n"
     ]
    }
   ],
   "source": [
    "batch_size = 128\n",
    "epochs_1rf = 70\n",
    "epochs_2rf = 50\n",
    "lr_1rf = 2e-4\n",
    "lr_2rf = 1e-5  \n",
    "beta1 = 0.5\n",
    "save_every = 10\n",
    "data_root = './data'\n",
    "base_channels = 64\n",
    "input_nc = 1\n",
    "output_nc = 1\n",
    "img_size = 28\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "print(f\"使用设备: {device}\")\n",
    "if torch.cuda.is_available():\n",
    "    torch.backends.cuda.matmul.allow_tf32 = True\n",
    "    torch.backends.cudnn.allow_tf32 = True\n",
    "    torch.set_float32_matmul_precision('high')\n",
    "    print(f\"GPU设备: {torch.cuda.get_device_name()}\")\n",
    "num_samples = 1000  # 用于计算IS和FID的样本数量\n",
    "sampling_steps_1rf = 50  # 1-Rectified Flow采样步数\n",
    "sampling_steps_2rf = 5   # 2-Rectified Flow采样步数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "22ad9421",
   "metadata": {},
   "source": [
    "**参数说明**\n",
    "\n",
    "超参数与数据/模型设置\n",
    "| 参数名 | 默认值 | 含义 | 备注/建议 |\n",
    "|---|---:|---|---|\n",
    "| batch_size | 128 | 训练/评估批大小 | 受显存影响 |\n",
    "| epochs_1rf | 70 | 1-Rectified Flow 训练轮数 | 可按收敛情况调整 |\n",
    "| epochs_2rf | 50 | 2-Rectified Flow 训练轮数 | 可按收敛情况调整 |\n",
    "| lr_1rf | 2e-4 | 1-RF 学习率 | AdamW |\n",
    "| lr_2rf | 1e-5 | 2-RF 学习率 | AdamW |\n",
    "| beta1 | 0.5 | 优化器 β1 | 代码未实际使用该变量 |\n",
    "| save_every | 10 | 模型保存间隔（epoch） | 最后一轮也会保存 |\n",
    "| data_root | ./data | MNIST 数据根目录 | 不存在会自动下载 |\n",
    "| base_channels | 64 | MiniUNet 基础通道数 | 控制模型容量 |\n",
    "| input_nc | 1 | 输入通道数 | MNIST 灰度图 |\n",
    "| output_nc | 1 | 输出通道数 | 生成单通道 |\n",
    "| img_size | 28 | 图像尺寸 | MNIST 固定为 28×\n",
    "\n",
    "设备与加速设置\n",
    "| 参数/开关 | 值 | 含义 | 备注 |\n",
    "|---|---|---|---|\n",
    "| device | cuda 或 cpu | 训练/推理设备选择 | 自动检测 CUDA |\n",
    "| torch.backends.cuda.matmul.allow_tf32 | True | 允许 TF32 matmul | Ampere+ GPU 加速 |\n",
    "| torch.backends.cudnn.allow_tf32 | True | 允许 TF32 cuDNN | 训练更快，精度轻微变化 |\n",
    "| torch.set_float32_matmul_precision | 'high' | 控制 fp32 matmul 精度/性能 | PyTorch 2.x 选项 |\n",
    "\n",
    "推理与评估参数\n",
    "| 参数名 | 默认值 | 含义 | 备注 |\n",
    "|---|---:|---|---|\n",
    "| num_samples | 1000 | 计算 IS/FID 时的样本数 | 越大越稳定，耗时更久 |\n",
    "| sampling_steps_1rf | 50 | 1-RF 欧拉法采样步数 | 与生成质量/速度权衡 |\n",
    "| sampling_steps_2rf | 5 | 2-RF 欧拉法采样步数 | 步数少，生成更快 |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11e7bfe0",
   "metadata": {},
   "source": [
    "## 2.RectifiedFlow类与MiniUnet类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c11abf44",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义RectifiedFlow类\n",
    "class RectifiedFlow:\n",
    "    \"\"\"Rectified Flow实现\"\"\"\n",
    "    \n",
    "    def vector_field(self, t, x):\n",
    "        \"\"\"向量场函数，用于torchdiffeq\n",
    "        \n",
    "        Args:\n",
    "            t: 时间标量\n",
    "            x: 当前状态，维度为 [B, C, H, W]\n",
    "        \n",
    "        Returns:\n",
    "            向量场，维度为 [B, C, H, W]\n",
    "        \"\"\"\n",
    "        # 将t扩展到与x相同的批次维度\n",
    "        t_batch = t.expand(x.size(0))\n",
    "        return self.model(x, t_batch)\n",
    "\n",
    "    def create_flow(self, x_1, t, x_0=None):\n",
    "        \"\"\"使用x_t = t * x_1 + (1 - t) * x_0公式构建x_0到x_1的流\n",
    "        \n",
    "        Args:\n",
    "            x_1: 原始图像，维度为 [B, C, H, W]\n",
    "            t: 一个标量，表示时间，时间范围为 [0, 1]，维度为 [B]\n",
    "            x_0: 噪声图像，维度为 [B, C, H, W]，默认值为None\n",
    "            \n",
    "        Returns:\n",
    "            x_t: 在时间t的图像，维度为 [B, C, H, W]\n",
    "            x_0: 噪声图像，维度为 [B, C, H, W]\n",
    "        \"\"\"\n",
    "        # 需要一个x0，x0服从高斯噪声\n",
    "        if x_0 is None:\n",
    "            x_0 = torch.randn_like(x_1)\n",
    "\n",
    "        t = t[:, None, None, None]  # [B, 1, 1, 1]\n",
    "\n",
    "        # 获得xt的值\n",
    "        x_t = t * x_1 + (1 - t) * x_0\n",
    "\n",
    "        return x_t, x_0\n",
    "\n",
    "    def mse_loss(self, v, x_1, x_0):\n",
    "        \"\"\"计算RectifiedFlow的损失函数\n",
    "        L = MSE(x_1 - x_0 - v(t))  匀速直线运动\n",
    "\n",
    "        Args:\n",
    "            v: 速度，维度为 [B, C, H, W]\n",
    "            x_1: 原始图像，维度为 [B, C, H, W]\n",
    "            x_0: 噪声图像，维度为 [B, C, H, W]\n",
    "        \"\"\"\n",
    "        loss = F.mse_loss(x_1 - x_0, v)\n",
    "        return loss\n",
    "    \n",
    "    def set_model(self, model):\n",
    "        \"\"\"设置模型引用，用于向量场计算\n",
    "        \n",
    "        Args:\n",
    "            model: 训练好的模型\n",
    "        \"\"\"\n",
    "        self.model = model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "226bb54f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义MiniUnet模型组件\n",
    "class DownLayer(nn.Module):\n",
    "    \"\"\"MiniUnet的下采样层 Resnet\"\"\"\n",
    "    \n",
    "    def __init__(self, in_channels, out_channels, time_emb_dim=16, downsample=False):\n",
    "        super(DownLayer, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.bn1 = nn.BatchNorm2d(out_channels)\n",
    "        self.bn2 = nn.BatchNorm2d(out_channels)\n",
    "\n",
    "        self.act = nn.ReLU()\n",
    "\n",
    "        # 线性层，用于时间编码换通道 [B, dim] -> [B, in_channels]\n",
    "        self.fc = nn.Linear(time_emb_dim, in_channels)\n",
    "\n",
    "        if in_channels != out_channels:\n",
    "            self.shortcut = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n",
    "        else:\n",
    "            self.shortcut = None\n",
    "\n",
    "        # 降采样\n",
    "        self.downsample = downsample\n",
    "        if downsample:\n",
    "            self.pool = nn.MaxPool2d(2)\n",
    "\n",
    "        self.in_channels = in_channels\n",
    "\n",
    "    def forward(self, x, temb):\n",
    "        # x: [B, C, H, W]\n",
    "        res = x\n",
    "        x += self.fc(temb)[:, :, None, None]  # [B, in_channels, 1, 1]\n",
    "        x = self.conv1(x)\n",
    "        x = self.bn1(x)\n",
    "        x = self.act(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.bn2(x)\n",
    "        x = self.act(x)\n",
    "\n",
    "        if self.shortcut is not None:\n",
    "            res = self.shortcut(res)\n",
    "\n",
    "        x = x + res\n",
    "\n",
    "        if self.downsample:\n",
    "            x = self.pool(x)\n",
    "\n",
    "        return x\n",
    "\n",
    "class UpLayer(nn.Module):\n",
    "    \"\"\"MiniUnet的上采样层\"\"\"\n",
    "    \n",
    "    def __init__(self, in_channels, out_channels, time_emb_dim=16, upsample=False):\n",
    "        super(UpLayer, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.bn1 = nn.BatchNorm2d(out_channels)\n",
    "        self.bn2 = nn.BatchNorm2d(out_channels)\n",
    "\n",
    "        self.act = nn.ReLU()\n",
    "\n",
    "        # 线性层，用于时间编码换通道\n",
    "        self.fc = nn.Linear(time_emb_dim, in_channels)\n",
    "\n",
    "        if in_channels != out_channels:\n",
    "            self.shortcut = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n",
    "        else:\n",
    "            self.shortcut = None\n",
    "\n",
    "        self.upsample = upsample\n",
    "        if upsample:\n",
    "            self.upsample = nn.Upsample(scale_factor=2)\n",
    "\n",
    "    def forward(self, x, temb):\n",
    "        # 上采样\n",
    "        if self.upsample:\n",
    "            x = self.upsample(x)\n",
    "        res = x\n",
    "\n",
    "        x += self.fc(temb)[:, :, None, None]\n",
    "        x = self.conv1(x)\n",
    "        x = self.bn1(x)\n",
    "        x = self.act(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.bn2(x)\n",
    "        x = self.act(x)\n",
    "\n",
    "        if self.shortcut is not None:\n",
    "            res = self.shortcut(res)\n",
    "        x = x + res\n",
    "\n",
    "        return x\n",
    "\n",
    "class MiddleLayer(nn.Module):\n",
    "    \"\"\"MiniUnet的中间层\"\"\"\n",
    "    \n",
    "    def __init__(self, in_channels, out_channels, time_emb_dim=16):\n",
    "        super(MiddleLayer, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)\n",
    "        self.bn1 = nn.BatchNorm2d(out_channels)\n",
    "        self.bn2 = nn.BatchNorm2d(out_channels)\n",
    "\n",
    "        self.act = nn.ReLU()\n",
    "\n",
    "        # 线性层，用于时间编码换通道\n",
    "        self.fc = nn.Linear(time_emb_dim, in_channels)\n",
    "\n",
    "        if in_channels != out_channels:\n",
    "            self.shortcut = nn.Conv2d(in_channels, out_channels, kernel_size=1)\n",
    "        else:\n",
    "            self.shortcut = None\n",
    "\n",
    "    def forward(self, x, temb):\n",
    "        res = x\n",
    "\n",
    "        x += self.fc(temb)[:, :, None, None]\n",
    "        x = self.conv1(x)\n",
    "        x = self.bn1(x)\n",
    "        x = self.act(x)\n",
    "        x = self.conv2(x)\n",
    "        x = self.bn2(x)\n",
    "        x = self.act(x)\n",
    "\n",
    "        if self.shortcut is not None:\n",
    "            x = self.shortcut(x)\n",
    "        x = x + res\n",
    "\n",
    "        return x\n",
    "\n",
    "# 定义MiniUnet模型\n",
    "class MiniUnet(nn.Module):\n",
    "    \"\"\"采用MiniUnet，对MNIST数据做生成\n",
    "        两个下采样block 一个中间block 两个上采样block\n",
    "    \"\"\"\n",
    "    \n",
    "    def __init__(self, base_channels=16, time_emb_dim=None):\n",
    "        super(MiniUnet, self).__init__()\n",
    "\n",
    "        if time_emb_dim is None:\n",
    "            self.time_emb_dim = base_channels\n",
    "\n",
    "        self.base_channels = base_channels\n",
    "\n",
    "        self.conv_in = nn.Conv2d(1, base_channels, kernel_size=3, padding=1)\n",
    "\n",
    "        # 多个Layer构成block\n",
    "        self.down1 = nn.ModuleList([\n",
    "            DownLayer(base_channels, base_channels * 2, time_emb_dim=self.time_emb_dim, downsample=False),\n",
    "            DownLayer(base_channels * 2, base_channels * 2, time_emb_dim=self.time_emb_dim)\n",
    "        ])\n",
    "        self.maxpool1 = nn.MaxPool2d(2)\n",
    "\n",
    "        self.down2 = nn.ModuleList([\n",
    "            DownLayer(base_channels * 2, base_channels * 4, time_emb_dim=self.time_emb_dim, downsample=False),\n",
    "            DownLayer(base_channels * 4, base_channels * 4, time_emb_dim=self.time_emb_dim)\n",
    "        ])\n",
    "        self.maxpool2 = nn.MaxPool2d(2)\n",
    "\n",
    "        self.middle = MiddleLayer(base_channels * 4, base_channels * 4, time_emb_dim=self.time_emb_dim)\n",
    "\n",
    "        self.upsample1 = nn.Upsample(scale_factor=2)\n",
    "        self.up1 = nn.ModuleList([\n",
    "            UpLayer(base_channels * 8, base_channels * 2, time_emb_dim=self.time_emb_dim, upsample=False),\n",
    "            UpLayer(base_channels * 2, base_channels * 2, time_emb_dim=self.time_emb_dim)\n",
    "        ])\n",
    "        self.upsample2 = nn.Upsample(scale_factor=2)\n",
    "        self.up2 = nn.ModuleList([\n",
    "            UpLayer(base_channels * 4, base_channels, time_emb_dim=self.time_emb_dim, upsample=False),\n",
    "            UpLayer(base_channels, base_channels, time_emb_dim=self.time_emb_dim)\n",
    "        ])\n",
    "\n",
    "        self.conv_out = nn.Conv2d(base_channels, 1, kernel_size=1, padding=0)\n",
    "\n",
    "    def time_emb(self, t, dim):\n",
    "        \"\"\"对时间进行正弦函数的编码，单一维度\n",
    "        \n",
    "        Args:\n",
    "            t (float): 时间，维度为[B]\n",
    "            dim (int): 编码的维度\n",
    "\n",
    "        Returns:\n",
    "            torch.Tensor: 编码后的时间，维度为[B, dim]\n",
    "        \"\"\"\n",
    "        # 生成正弦编码\n",
    "        # 把t映射到[0, 1000]\n",
    "        t = t * 1000\n",
    "        # 10000^k k=torch.linspace……\n",
    "        freqs = torch.pow(10000, torch.linspace(0, 1, dim // 2)).to(t.device)\n",
    "        sin_emb = torch.sin(t[:, None] / freqs)\n",
    "        cos_emb = torch.cos(t[:, None] / freqs)\n",
    "\n",
    "        return torch.cat([sin_emb, cos_emb], dim=-1)\n",
    "\n",
    "    \n",
    "\n",
    "    def forward(self, x, t):\n",
    "        \"\"\"前向传播函数\n",
    "\n",
    "        Args:\n",
    "            x (torch.Tensor): 输入数据，维度为[B, C, H, W]\n",
    "            t (torch.Tensor): 时间，维度为[B]\n",
    "        \"\"\"\n",
    "        # x:(B, C, H, W)\n",
    "        # 时间编码加上\n",
    "        x = self.conv_in(x)\n",
    "        # 时间编码\n",
    "        temb = self.time_emb(t, self.base_channels)\n",
    "        \n",
    "        # 下采样\n",
    "        for layer in self.down1:\n",
    "            x = layer(x, temb)\n",
    "        x1 = x\n",
    "        x = self.maxpool1(x)\n",
    "        for layer in self.down2:\n",
    "            x = layer(x, temb)\n",
    "        x2 = x\n",
    "        x = self.maxpool2(x)\n",
    "\n",
    "        # 中间层\n",
    "        x = self.middle(x, temb)\n",
    "\n",
    "        # 上采样\n",
    "        x = torch.cat([self.upsample1(x), x2], dim=1)\n",
    "        for layer in self.up1:\n",
    "            x = layer(x, temb)\n",
    "        x = torch.cat([self.upsample2(x), x1], dim=1)\n",
    "        for layer in self.up2:\n",
    "            x = layer(x, temb)\n",
    "\n",
    "        x = self.conv_out(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc37b255",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义ReflowDataset类\n",
    "class ReflowDataset(Dataset):\n",
    "    \"\"\"ReflowDataset\n",
    "    用于训练Reflow模型的数据集（内存版本）\n",
    "    \n",
    "    Args:\n",
    "        img_tensors (list): 图像张量列表\n",
    "        noise_tensors (list): 噪声张量列表\n",
    "        transform (optional): 图像transform. Defaults to None.\n",
    "    \"\"\"\n",
    "    \n",
    "    def __init__(self, img_tensors, noise_tensors, transform=None):\n",
    "        self.img_tensors = img_tensors\n",
    "        self.noise_tensors = noise_tensors\n",
    "        self.transform = transform\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.img_tensors)\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        img = self.img_tensors[idx]\n",
    "        noise = self.noise_tensors[idx]\n",
    "\n",
    "        if self.transform:\n",
    "            img = self.transform(img)\n",
    "\n",
    "        return {'img': img, 'noise': noise, 'label': 0}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "76f347f7",
   "metadata": {},
   "source": [
    "## 3.数据集加载与模型初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "2cd9e676",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在加载MNIST数据集从 ./data...\n",
      "MNIST数据集加载成功，数据集大小: 60000\n"
     ]
    }
   ],
   "source": [
    "# 加载MNIST数据集\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor()\n",
    "])\n",
    "\n",
    "print(f\"正在加载MNIST数据集从 {data_root}...\")\n",
    "mnist_dataset = datasets.MNIST(root=data_root, train=True, download=True, transform=transform)\n",
    "mnist_dataloader = DataLoader(mnist_dataset, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "print(f\"MNIST数据集加载成功，数据集大小: {len(mnist_dataset)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "c3f1fcda",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "初始化1-Rectified Flow模型...\n",
      "1-Rectified Flow模型参数数量: 5299457\n"
     ]
    }
   ],
   "source": [
    "# 初始化1-Rectified Flow模型\n",
    "print(\"初始化1-Rectified Flow模型...\")\n",
    "model_1rf = MiniUnet(base_channels=base_channels).to(device)\n",
    "rf = RectifiedFlow()\n",
    "\n",
    "# 定义优化器和损失函数\n",
    "optimizer_1rf = optim.AdamW(model_1rf.parameters(), lr=lr_1rf, weight_decay=0.1)\n",
    "scheduler_1rf = optim.lr_scheduler.StepLR(optimizer_1rf, step_size=30, gamma=0.1)\n",
    "\n",
    "# 训练历史记录\n",
    "losses_history_1rf = []\n",
    "\n",
    "# 创建保存目录\n",
    "os.makedirs('./checkpoints/1rf', exist_ok=True)\n",
    "os.makedirs('./results/1rf', exist_ok=True)\n",
    "os.makedirs('./data', exist_ok=True)\n",
    "\n",
    "print(f\"1-Rectified Flow模型参数数量: {sum(p.numel() for p in model_1rf.parameters())}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ae07d71",
   "metadata": {},
   "source": [
    "## 4.训练1-Rectified Flow模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6af84bfc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练1-Rectified Flow，总轮数: 70\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 1/70: 100%|██████████| 469/469 [01:19<00:00,  5.93it/s, loss=0.14] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/70 - Loss: 0.1811\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 2/70: 100%|██████████| 469/469 [01:10<00:00,  6.64it/s, loss=0.114]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 2/70 - Loss: 0.1190\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 3/70: 100%|██████████| 469/469 [01:02<00:00,  7.44it/s, loss=0.0966]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 3/70 - Loss: 0.1088\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 4/70: 100%|██████████| 469/469 [01:17<00:00,  6.08it/s, loss=0.102] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 4/70 - Loss: 0.1037\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 5/70: 100%|██████████| 469/469 [01:09<00:00,  6.72it/s, loss=0.0982] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 5/70 - Loss: 0.1005\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 6/70: 100%|██████████| 469/469 [01:03<00:00,  7.43it/s, loss=0.109] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 6/70 - Loss: 0.0981\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 7/70: 100%|██████████| 469/469 [01:17<00:00,  6.08it/s, loss=0.0902]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 7/70 - Loss: 0.0964\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 8/70: 100%|██████████| 469/469 [01:03<00:00,  7.44it/s, loss=0.0914]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 8/70 - Loss: 0.0951\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 9/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0968]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 9/70 - Loss: 0.0941\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 10/70: 100%|██████████| 469/469 [01:10<00:00,  6.68it/s, loss=0.0875]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 10/70 - Loss: 0.0936\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_10.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 11/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.0966]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 11/70 - Loss: 0.0923\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 12/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0908]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 12/70 - Loss: 0.0917\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 13/70: 100%|██████████| 469/469 [01:10<00:00,  6.66it/s, loss=0.0897]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 13/70 - Loss: 0.0916\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 14/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0991]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 14/70 - Loss: 0.0912\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 15/70: 100%|██████████| 469/469 [01:09<00:00,  6.71it/s, loss=0.0907]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 15/70 - Loss: 0.0906\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 16/70: 100%|██████████| 469/469 [01:10<00:00,  6.68it/s, loss=0.0897]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 16/70 - Loss: 0.0903\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 17/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0891]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 17/70 - Loss: 0.0896\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 18/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.0923]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 18/70 - Loss: 0.0893\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 19/70: 100%|██████████| 469/469 [01:03<00:00,  7.43it/s, loss=0.0882]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 19/70 - Loss: 0.0892\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 20/70: 100%|██████████| 469/469 [01:10<00:00,  6.68it/s, loss=0.0916]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 20/70 - Loss: 0.0889\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_20.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 21/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0937]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 21/70 - Loss: 0.0885\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 22/70: 100%|██████████| 469/469 [01:16<00:00,  6.10it/s, loss=0.0857]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 22/70 - Loss: 0.0885\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 23/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0979]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 23/70 - Loss: 0.0880\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 24/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0841]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 24/70 - Loss: 0.0876\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 25/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.0888]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 25/70 - Loss: 0.0878\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 26/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.081] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 26/70 - Loss: 0.0873\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 27/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0847] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 27/70 - Loss: 0.0873\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 28/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.0932]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 28/70 - Loss: 0.0870\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 29/70: 100%|██████████| 469/469 [01:09<00:00,  6.72it/s, loss=0.0923]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 29/70 - Loss: 0.0870\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 30/70: 100%|██████████| 469/469 [01:17<00:00,  6.07it/s, loss=0.0865]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 30/70 - Loss: 0.0867\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_30.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 31/70: 100%|██████████| 469/469 [01:02<00:00,  7.46it/s, loss=0.0885]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 31/70 - Loss: 0.0846\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 32/70: 100%|██████████| 469/469 [01:09<00:00,  6.72it/s, loss=0.0836]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 32/70 - Loss: 0.0840\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 33/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0833]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 33/70 - Loss: 0.0841\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 34/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.0782]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 34/70 - Loss: 0.0839\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 35/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0798]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 35/70 - Loss: 0.0837\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 36/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0958]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 36/70 - Loss: 0.0838\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 37/70: 100%|██████████| 469/469 [01:10<00:00,  6.68it/s, loss=0.0859]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 37/70 - Loss: 0.0836\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 38/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0832]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 38/70 - Loss: 0.0836\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 39/70: 100%|██████████| 469/469 [01:09<00:00,  6.71it/s, loss=0.0788]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 39/70 - Loss: 0.0836\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 40/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0826]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 40/70 - Loss: 0.0833\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_40.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 41/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0819]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 41/70 - Loss: 0.0833\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 42/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0953]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 42/70 - Loss: 0.0831\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 43/70: 100%|██████████| 469/469 [01:09<00:00,  6.71it/s, loss=0.0831]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 43/70 - Loss: 0.0834\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 44/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0779]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 44/70 - Loss: 0.0832\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 45/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.08]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 45/70 - Loss: 0.0833\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 46/70: 100%|██████████| 469/469 [01:09<00:00,  6.72it/s, loss=0.0812]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 46/70 - Loss: 0.0832\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 47/70: 100%|██████████| 469/469 [01:17<00:00,  6.07it/s, loss=0.09]  \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 47/70 - Loss: 0.0832\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 48/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0887]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 48/70 - Loss: 0.0831\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 49/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.0801]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 49/70 - Loss: 0.0827\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 50/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0816]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 50/70 - Loss: 0.0831\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_50.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 51/70: 100%|██████████| 469/469 [01:09<00:00,  6.71it/s, loss=0.0793]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 51/70 - Loss: 0.0829\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 52/70: 100%|██████████| 469/469 [01:17<00:00,  6.08it/s, loss=0.0838]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 52/70 - Loss: 0.0831\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 53/70: 100%|██████████| 469/469 [01:02<00:00,  7.48it/s, loss=0.0845]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 53/70 - Loss: 0.0830\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 54/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0937]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 54/70 - Loss: 0.0829\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 55/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0829]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 55/70 - Loss: 0.0830\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 56/70: 100%|██████████| 469/469 [01:17<00:00,  6.09it/s, loss=0.0867]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 56/70 - Loss: 0.0830\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 57/70: 100%|██████████| 469/469 [01:03<00:00,  7.44it/s, loss=0.0846]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 57/70 - Loss: 0.0828\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 58/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0824]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 58/70 - Loss: 0.0829\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 59/70: 100%|██████████| 469/469 [01:17<00:00,  6.07it/s, loss=0.0819]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 59/70 - Loss: 0.0830\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 60/70: 100%|██████████| 469/469 [01:02<00:00,  7.47it/s, loss=0.0821]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 60/70 - Loss: 0.0827\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_60.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 61/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0795]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 61/70 - Loss: 0.0824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 62/70: 100%|██████████| 469/469 [01:09<00:00,  6.70it/s, loss=0.0867]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 62/70 - Loss: 0.0828\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 63/70: 100%|██████████| 469/469 [01:10<00:00,  6.69it/s, loss=0.0843]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 63/70 - Loss: 0.0826\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 64/70: 100%|██████████| 469/469 [01:17<00:00,  6.08it/s, loss=0.0826]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 64/70 - Loss: 0.0825\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 65/70: 100%|██████████| 469/469 [01:02<00:00,  7.45it/s, loss=0.0806]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 65/70 - Loss: 0.0824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 66/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.0952]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 66/70 - Loss: 0.0824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 67/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.0841]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 67/70 - Loss: 0.0823\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 68/70: 100%|██████████| 469/469 [01:17<00:00,  6.07it/s, loss=0.0819]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 68/70 - Loss: 0.0824\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 69/70: 100%|██████████| 469/469 [01:10<00:00,  6.70it/s, loss=0.08]    \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 69/70 - Loss: 0.0823\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 70/70: 100%|██████████| 469/469 [01:02<00:00,  7.47it/s, loss=0.0863]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 70/70 - Loss: 0.0825\n",
      "模型已保存到 ./checkpoints/1rf/miniunet_70.pth\n",
      "1-Rectified Flow训练完成！\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# 训练1-Rectified Flow模型\n",
    "print(f\"开始训练1-Rectified Flow，总轮数: {epochs_1rf}\")\n",
    "\n",
    "for epoch in range(1,epochs_1rf+1):\n",
    "    epoch_loss = 0.0\n",
    "    num_batches = 0\n",
    "    \n",
    "    pbar = tqdm(mnist_dataloader, desc=f'Epoch {epoch}/{epochs_1rf}')\n",
    "    for i, (imgs, labels) in enumerate(pbar):\n",
    "        imgs = imgs.to(device)\n",
    "        labels = labels.to(device)\n",
    "        \n",
    "        # 均匀采样[0, 1]的时间t\n",
    "        t = torch.rand(imgs.size(0)).to(device)\n",
    "        \n",
    "        # 生成flow\n",
    "        x_t, x_0 = rf.create_flow(imgs, t)\n",
    "        \n",
    "        optimizer_1rf.zero_grad()\n",
    "        \n",
    "        # 预测速度场\n",
    "        v_pred = model_1rf(x=x_t, t=t)\n",
    "        \n",
    "        # 计算损失\n",
    "        loss = rf.mse_loss(v_pred, imgs, x_0)\n",
    "        \n",
    "        loss.backward()\n",
    "        optimizer_1rf.step()\n",
    "        \n",
    "        # 记录损失\n",
    "        epoch_loss += loss.item()\n",
    "        num_batches += 1\n",
    "        \n",
    "        # 更新进度条\n",
    "        pbar.set_postfix({'loss': loss.item()})\n",
    "    \n",
    "    # 计算平均损失\n",
    "    avg_loss = epoch_loss / num_batches\n",
    "    losses_history_1rf.append(avg_loss)\n",
    "    \n",
    "    # 更新学习率\n",
    "    scheduler_1rf.step()\n",
    "    \n",
    "    # 打印epoch信息\n",
    "    print(f\"Epoch {epoch}/{epochs_1rf} - Loss: {avg_loss:.4f}\")\n",
    "    \n",
    "    # 保存模型\n",
    "    if epoch % save_every == 0 or epoch == epochs_1rf:\n",
    "        torch.save({\n",
    "            'model': model_1rf.state_dict(),\n",
    "            'optimizer': optimizer_1rf.state_dict(),\n",
    "            'epoch': epoch,\n",
    "            'loss': avg_loss,\n",
    "            'loss_history': losses_history_1rf\n",
    "        }, f'./checkpoints/1rf/miniunet_{epoch}.pth')\n",
    "        print(f\"模型已保存到 ./checkpoints/1rf/miniunet_{epoch}.pth\")\n",
    "\n",
    "print(\"1-Rectified Flow训练完成！\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "a667544b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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Wqu0hcNhmaaplStX6k9/+pO+973vxYf43XrrrVq4cKEef/xxJSUlafLkyRo9erQWLVokKdZTcOutt+q3v/2tLrnkEv3zn//UqFGjtGrVKp1xxhlaunRp/Dz9+vXT+PHjJane85pq5kFJ0lVXXaXx48fr+9///gl/Hz/84Q+1d+9ezZ49W4FAQLfffrsqKio0Z84cSdJvfvMbvfnmm3riiSeUmpqqSZMmnfB7SLHgcHhYPbzH5nhefPFF3XDDDZo0aZIuueQSPf/887r00kv16aefql+/fkpNTdW6detUWlqq/v3767///a8kad26dRo7dqxatGih3NxcSbEQe/gwzXA4fMyhfTWGDx+uvLw8uVwu9ezZUzNnzpTD4dDjjz+uXbt2qXPnzvrjH/+o22+/Xdu3bz/mucrLy/Xll1+qW7duevbZZ+X3+/X000/XWuFPkl599VU98cQTtfZ5vV79/ve/V3l5ea35UV9//bWcTmetfVLse6+qqlKvXr0adXgqADQFwhQA2Fz//v31xRdfHPX5miF8+fn5tf7IHjRokP72t79JivX0zJkzR6+++qquuuoqSbE/ykePHq28vDzl5OTod7/7ncaNG6cHHnhAkjR06FCVlJRo27ZtOuOMM+JzW1JSUpSVlXXCc5oOnwfl9XrVpUuXEz7HokWL9OGHH2rZsmXq27evpNgiCXfeeaeeffZZhUIhPf/883rwwQd10003SYrNJbviiitO6H0kxXv0auzZs0eZmZn1Ova+++7Tddddp0ceeURSLNicc845uv/++/Xmm2+qf//+WrdunYqKinTVVVfp+eef1759+7Rv3z4NGDCgzvkO770rLS095uIeNRwOh9q1a6dRo0Zp/Pjx8fMuWLBAb7/9ttauXauysjKFQiGZphlf5c/j8Sg5OVmS9PDDD2vWrFnauHGjunfvrj//+c+65JJLZBiGvF6vkpKSdP3118vpdGrWrFnyer11FqC47bbbtHjxYnk8nlqfo6ysTJFIpM7PQDgcVlVVlTZv3nzEnloAsBPCFADYXHJy8hH/wP6mjIwMvfPOO/rqq680btw4zZgxIx601qxZI9M0dfXVV9c5btOmTfL7/dq1a1etRSXcbrdeffXVRvscjaGmB+ebQ8kkafv27aqsrFQ4HNa5554b33/BBRc06L0+/PDDWqv5fTNcHU1hYaG2bdtWa5ijw+HQsGHD9MYbb0iKLW6xbt06FRYW6oorrpDL5dKSJUvk9Xp19tlnH/XckUhEBw4cqHdbRo8erc8//1zXXXedHnjgAXXs2FF/+9vfFAgENHDgQDkcDpWXlysajapjx47xoaAPPvhg/Bw/+clPtHv3buXn52vkyJGSYkNPa+zfv19nnnlmfPvw5yRp4cKFddpVVFSkjh07KhKJ6Nlnnz3izyUANAeEKQA4RbhcLg0YMEADBgzQM888owceeCD+x2+N+fPnq3Xr1rX2devWLb4C2zfnL/33v/+V1+tVjx49mrbxJ8DpdGrp0qV12pqVlRUfMnb4nKL6zC86kj59+jRoNb9vhokahmHEnxs4cKBef/11tWjRQpMnT1b37t316quv6pxzzjnqEL68vDxFo1GFQqET6rFJT0/Xq6++qg4dOmjAgAF66aWXlJKSEv9st99+u3bu3BlfXOJwd955p6TY9bQOXygiEAjEH+/du1c//OEPj/jc0Tz55JNq0aKFZs6cqZ///Oe69NJL1aJFi3p/JgCwCxagAIBT0D333KPFixfr448/liSdddZZkmI9GzWBq3379nr88ce1fft2tWnTRu3atYvPn5JioeCKK67Qs88+W+vcCQkJqqysPHkf5jBnn322IpGIEhIS4p/D4/Ho8ccfV3FxsTp37iyHw1FrWOQnn3xyUtvYunVrZWdn64MPPojvi0aj+vDDD+M9jAMGDNCWLVu0Zs0ade7cWT169NDrr79+1B7IF154Qd/97ne1ePFiZWdnKz09PX7emoBmmmadIPfGG29o69atmj9/vmbOnKmRI0eqQ4cO2r17twYMGKD//e9/8dcuWrRIY8eOPWoYPNyVV16p7t27Ky8vT6tWrdL555+vYDCos88+Wz/96U+Peewnn3yiBx54QPfdd5++973vaeDAgbrkkku0b9++474vANgNPVMAcAoaOXKkBg4cqPvvv18LFy5U586dNW7cON16660qKipSu3bt9Mgjj2jt2rWaOXOmJOnuu+/Wr371K2VlZenCCy/UG2+8od27d+v666+vde5BgwbplVde0fDhw1VWVqby8vI6CxE0lWHDhumCCy7QNddco2nTpsnv9+vee+9VOBxWZmamDMPQ2LFjNWPGDKWlpSklJaXBC1B8G9OnT9f48ePVvn17DRs2TLNmzdJXX32l5557TpKU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l156qenz+cyhQ4fy3zEbGTt2rPnTn/601j671MUwzW/M3gIAAAAAHBdzpgAAAACgAQhTAAAAANAAhCkAAAAAaADCFAAAAAA0AGEKAAAAABqAMAUAAAAADUCYAgA0G7t3744/jkajikajDT5XQ68MUllZeVLfDwBgX4QpAECzEAgE1K9fPy1dulSStHHjRiUkJKioqKjW6zwejw4ePBjffvbZZ/XWW2/VOd/AgQP15ZdfHvX9lixZoosuuqjO/r59++r1118/4jGPP/64PvvsM02fPl2TJ0/WggULNG3aNEnSL3/5S913333H+5gAgGaEMAUAaBa8Xq/uuOMO3XHHHZKkhIQEJSQkKD09Xddff72efvrp+H6PxyNJikQi+t3vfqeKigpJUigUUjgc1po1a5Sfn69evXpJksLhsMLhsCQpGAwqEAho6dKl6tmzZ3xfJBLRBx98oLy8PL3yyitHbOOFF16oTZs2ye12y+12a9WqVbrqqqskSZ9//rl69eqlvLw85eXlafv27U30TQEAThaX1Q0AAKC+fvnLX6qyslKRSERer1c+n09SLGjVBCiHwyHDMCRJr732mjp37qyrr75aL7/8sr788kstXLhQ+fn58vv9OvfccyXFer1uu+02/fKXv9Sf//xnPfnkk9q9e7fatm2rLl26qLKyUq+88oruuusuPfLII1q0aJGeeOIJ/frXv4637dNPP9WoUaOUmJioAwcOyOPxKCUlRX/84x/17rvvauvWrXr11Vf1t7/9TV988YV++tOf6tFHHz3J3yAAoDEZJoO4AQA2FwwGdfDgQbnd7niPVGFhoXr16qW9e/fq5ptv1nnnnacbbrhBaWlp2rt3r8rLyzVw4EDNnTtXJSUlGjt2rJYsWaJ27dqpZ8+eev/995WTk3PE98vPz1f//v21detWud1uSdJvf/tbLVq0SJ988olKS0s1ZMgQXX755Zo+fXo8yJmmqfHjx+udd97R9ddfr4MHD+r+++/Xc889p02bNunZZ5/V8uXLNXHiRC1atOhkfX0AgCbCMD8AgO2tWLFCPXr0UFZWlu6//35JseDicBz9f2ObN29WQUGBbrvtNo0cOVKvvvqqFixYoE6dOqmwsFCXXXaZunbtesRjn376ad1www164oknNHnyZN1+++166aWXdO+992rnzp1KS0vThx9+qA8++EADBgxQKBRSXl6eRowYoW3btumGG25QOByWYRiaNGmSZs6cGT93cXGxWrVq1bhfEADAEoQpAIDtnXfeeTpw4IAmTZoU7ykKh8NyuY4+Wv3cc89VUVGR+vXrp2nTpmno0KEaO3asWrZsqaVLl2rhwoUqLi6uc1xeXp5mzpypX/3qV5IkwzB066236u2339a8efP09ttvx/cvXrxYL7zwgtxut1q3bq0+ffrojTfeUN++fXXnnXfq7rvv1pVXXqkOHTpow4YNkmIrEmZmZjbyNwQAsAJzpgAAzYrT6ZQklZWVKSkp6Ziv/c1vfqOPP/5Y99xzj2bOnKl169Zp06ZNuu666xQKhVRcXKxzzjlHpaWleuaZZzR8+HB9/fXXKigoUL9+/RQOhxWJRJSbm6sVK1bI4/HI6/VqyZIlGjVqlHJzczVgwABJksvl0sMPP6ylS5dq4sSJ+vrrr+V2u3X55Zfr+9//vq688kpt2LBB69atU7du3Zr8ewIAND16pgAAzdKePXuOO1yurKxMHTp00OrVq5WSkqJp06Zpz549Wrp0qd59912lpaVp9erV2rx5s4YPHy5Juvjii3Xw4EHt2rVLU6ZM0fjx47VixQpJsd6oF198Uddee61mzZoVD1KSdP3116tjx44aPny4qqqq1K1bN3m9Xn3wwQdyOBy69NJL9Y9//EOff/65+vbt23RfDADgpKFnCgDQrFRVVWnGjBlq3bq1OnfufMzXzpo1S1JsAYs1a9bINE3NnDlT//nPf/TPf/5TkvTJJ59o0qRJ+uSTT+RyuWQYhjwej3bu3Kk9e/boq6++0hNPPKEf/vCHkqTs7Gz961//Umpqaq33+uc//6nS0lKdc845WrZsmVwul3r16qUhQ4ZIkq666iqdd955MgxD5513XmN/LQAAC9AzBQBoNsLhsJ588kmVlpbq/fff1+DBgyXFricVjUbjr4lGoyosLNRNN92kgQMHKisrS5MnT9ayZcv0hz/8QX/961/jwwUHDx6saDSqRx55RJL0zDPPKCMjQ1dccYXefvtt7d69W4FAQMnJyZJiPVc1QaqwsFCHL4q7fv169ejRQ5deeqlGjhyp3r17q7KyUpLUrl07JSYm6sILL4yv/gcAaN4IUwCAZuOzzz7TsGHD9LOf/Uxvv/22rrzySkmHLsZ7+OOMjAxlZ2frqaee0t69e/Xss8/q5ptv1p/+9CelpKTotddeU2JiohwOh5588knNmTNHlZWVuummm1RSUqLly5frhhtu0EUXXaTJkycrJSVFhmHELwAsSY8++qhuueWW+PagQYP08ssvq3fv3vL5fDp48KCuv/56FRQU6PLLL1eHDh20YMECPfvssyf1ewMANA2G+QEAmo17771Xffr00W9/+1vddNNN8TlTs2fPjr+mJkw5HA5Nnz49vr9du3b685//rCuvvFJr1qzRjBkzdOedd0qKhaD169fXWWo9GAyqqqoqvt2vXz9NmDBBjzzyiKLRqKqqqrRgwQJJ0tKlS/Xss8/q/fff1y233KJZs2bJ6XTqzjvvVNeuXXXDDTfoscce0/vvv6+rrrpKa9eu1RNPPNFUXxUA4CTgor0AgGbpeEujn2zLly/Xp59+qnHjxiktLS2+f8GCBUpLS4sPSZSk1atXKyMjQ1lZWRa0FADQWAhTAAAAANAAzJkCAAAAgAYgTAEAAABAAxCmAAAAAKABCFMAAAAA0ACEKQAAAABoAMIUAAAAADQAYQoAAAAAGoAwBQAAAAAN8P8DL2koWz3EnwMAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制1-Rectified Flow损失曲线\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(losses_history_1rf)\n",
    "plt.xlabel('训练轮数')\n",
    "plt.ylabel('损失')\n",
    "plt.title('1-Rectified Flow训练损失')\n",
    "plt.grid(True)\n",
    "plt.savefig('./results/1rf/loss_curve.png', dpi=600)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f69fa1ad",
   "metadata": {},
   "source": [
    "## 5.使用1-Rectified Flow推理测试同时为2-Rectified Flow准备训练数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "beda4f89",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1-Rectified Flow推理函数\n",
    "def infer_1rf(model, rf, num_samples=10, steps=50, save_path='./results/1rf'):\n",
    "    \"\"\"1-Rectified Flow推理函数\n",
    "    \n",
    "    Args:\n",
    "        model: 训练好的模型\n",
    "        rf: RectifiedFlow实例\n",
    "        num_samples: 生成样本数量\n",
    "        steps: 采样步数\n",
    "        save_path: 保存路径\n",
    "    \"\"\"\n",
    "    model.eval()\n",
    "    os.makedirs(save_path, exist_ok=True)\n",
    "    \n",
    "    generated_images = []\n",
    "    \n",
    "    # 设置模型引用到RectifiedFlow\n",
    "    rf.set_model(model)\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        pbar = tqdm(range(num_samples), desc=f'生成1-RF样本 (步数: {steps})')\n",
    "        for i in pbar:\n",
    "            # 初始噪声\n",
    "            x_0 = torch.randn(1, 1, img_size, img_size).to(device)\n",
    "            \n",
    "            # 使用torchdiffeq进行ODE求解\n",
    "            t_span = torch.linspace(0, 1, steps).to(device)\n",
    "            trajectory = odeint(rf.vector_field, x_0, t_span, method='euler')\n",
    "            x_t = trajectory[-1]  # 取最后一个时间点的结果\n",
    "            \n",
    "            # 保存生成的图像\n",
    "            raw = x_t[0, 0].cpu().numpy()  # (28,28)\n",
    "            # 归一化到 0-255（防止值域异常）\n",
    "            norm = (raw - raw.min()) / (raw.max() - raw.min() + 1e-8)\n",
    "            img_uint8 = (norm * 255).astype(np.uint8)\n",
    "            cv2.imwrite(os.path.join(save_path, f'gen_{i}.png'), img_uint8)\n",
    "            generated_images.append(x_t[0].cpu())\n",
    "            \n",
    "            # 更新进度条\n",
    "            pbar.set_postfix({'样本': f'{i+1}/{num_samples}'})\n",
    "    \n",
    "    return torch.stack(generated_images)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "cdc5f6cb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "运行1-Rectified Flow推理...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "生成1-RF样本 (步数: 50): 100%|██████████| 20/20 [00:04<00:00,  4.37it/s, 样本=20/20]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "生成了 20 张图像\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# 运行1-Rectified Flow推理并生成图像\n",
    "print(\"运行1-Rectified Flow推理...\")\n",
    "generated_images_1rf = infer_1rf(model_1rf, rf, num_samples=20, steps=sampling_steps_1rf)\n",
    "print(f\"生成了 {len(generated_images_1rf)} 张图像\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "39d1892a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "正在生成 10000 个样本用于2-Rectified Flow训练...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 10000/10000 [31:58<00:00,  5.21it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reflow数据集创建完成，共 10000 个样本\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# 创建Reflow数据集（用于2-Rectified Flow训练，内存版本）\n",
    "def create_reflow_dataset(model, rf, num_samples=5000, steps=50):\n",
    "    \"\"\"创建Reflow数据集（内存版本）\n",
    "    \n",
    "    Args:\n",
    "        model: 训练好的1-Rectified Flow模型\n",
    "        rf: RectifiedFlow实例\n",
    "        num_samples: 生成样本数量\n",
    "        steps: 采样步数\n",
    "    \n",
    "    Returns:\n",
    "        img_tensors: 生成的图像张量列表\n",
    "        noise_tensors: 对应的噪声张量列表\n",
    "    \"\"\"\n",
    "    model.eval()\n",
    "    \n",
    "    print(f\"正在生成 {num_samples} 个样本用于2-Rectified Flow训练...\")\n",
    "    \n",
    "    img_tensors = []\n",
    "    noise_tensors = []\n",
    "    \n",
    "    # 设置模型引用到RectifiedFlow\n",
    "    rf.set_model(model)\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        for i in tqdm(range(num_samples)):\n",
    "            # 初始噪声\n",
    "            x_0 = torch.randn(1, 1, img_size, img_size).to(device)\n",
    "            \n",
    "            # 使用torchdiffeq进行ODE求解\n",
    "            t_span = torch.linspace(0, 1, steps).to(device)\n",
    "            trajectory = odeint(rf.vector_field, x_0, t_span, method='euler')\n",
    "            x_1 = trajectory[-1]  # 取最后一个时间点的结果\n",
    "            \n",
    "            # 收集图像和噪声\n",
    "            img_tensors.append(x_1[0].cpu())\n",
    "            noise_tensors.append(x_0[0].cpu())\n",
    "    \n",
    "    print(f\"Reflow数据集创建完成，共 {len(img_tensors)} 个样本\")\n",
    "    return img_tensors, noise_tensors\n",
    "\n",
    "# 创建Reflow数据集\n",
    "img_tensors, noise_tensors = create_reflow_dataset(model_1rf, rf, num_samples=10000, steps=sampling_steps_1rf)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9f73d73",
   "metadata": {},
   "source": [
    "## 6.初始化2-recctified flow模型并训练"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "fbdb46c0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "初始化2-Rectified Flow模型...\n",
      "已加载1-Rectified Flow预训练权重\n"
     ]
    }
   ],
   "source": [
    "# 初始化2-Rectified Flow模型\n",
    "print(\"初始化2-Rectified Flow模型...\")\n",
    "model_2rf = MiniUnet(base_channels=base_channels).to(device)\n",
    "\n",
    "# 加载1-Rectified Flow预训练权重\n",
    "checkpoint_1rf = torch.load(f'./checkpoints/1rf/miniunet_{epochs_1rf}.pth')\n",
    "model_2rf.load_state_dict(checkpoint_1rf['model'])\n",
    "print(\"已加载1-Rectified Flow预训练权重\")\n",
    "\n",
    "# 定义优化器和损失函数\n",
    "optimizer_2rf = optim.AdamW(model_2rf.parameters(), lr=lr_2rf, weight_decay=0.1)\n",
    "scheduler_2rf = optim.lr_scheduler.StepLR(optimizer_2rf, step_size=10, gamma=0.1)\n",
    "\n",
    "# 训练历史记录\n",
    "losses_history_2rf = []\n",
    "\n",
    "# 创建保存目录\n",
    "os.makedirs('./checkpoints/2rf', exist_ok=True)\n",
    "os.makedirs('./results/2rf', exist_ok=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "37654664",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Reflow数据集创建成功，数据集大小: 10000\n"
     ]
    }
   ],
   "source": [
    "# 创建Reflow数据集加载器\n",
    "reflow_transform = transforms.Lambda(lambda x: x)  # 已经是tensor，不需要变换\n",
    "reflow_dataset = ReflowDataset(img_tensors=img_tensors,\n",
    "                               noise_tensors=noise_tensors,\n",
    "                               transform=reflow_transform)\n",
    "reflow_dataloader = DataLoader(reflow_dataset, batch_size=batch_size, shuffle=True, num_workers=4)\n",
    "print(f\"Reflow数据集创建成功，数据集大小: {len(reflow_dataset)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a012802a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "开始训练2-Rectified Flow，总轮数: 50\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 1/50: 100%|██████████| 79/79 [00:04<00:00, 16.10it/s, loss=0.0119]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/50 - Loss: 0.0192\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 2/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.0119] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 2/50 - Loss: 0.0102\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 3/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.0138] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 3/50 - Loss: 0.0081\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 4/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00805]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 4/50 - Loss: 0.0074\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 5/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00659]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 5/50 - Loss: 0.0064\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 6/50: 100%|██████████| 79/79 [00:18<00:00,  4.19it/s, loss=0.0066] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 6/50 - Loss: 0.0061\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 7/50: 100%|██████████| 79/79 [00:11<00:00,  6.68it/s, loss=0.00625]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 7/50 - Loss: 0.0060\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 8/50: 100%|██████████| 79/79 [00:04<00:00, 16.78it/s, loss=0.00631]   \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 8/50 - Loss: 0.0058\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 9/50: 100%|██████████| 79/79 [00:18<00:00,  4.20it/s, loss=0.00463]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 9/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 10/50: 100%|██████████| 79/79 [00:11<00:00,  6.72it/s, loss=0.00763]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 10/50 - Loss: 0.0051\n",
      "模型已保存到 ./checkpoints/2rf/miniunet_10.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 11/50: 100%|██████████| 79/79 [00:11<00:00,  6.72it/s, loss=0.0114] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 11/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 12/50: 100%|██████████| 79/79 [00:04<00:00, 16.62it/s, loss=0.00825]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 12/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 13/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.0051] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 13/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 14/50: 100%|██████████| 79/79 [00:18<00:00,  4.19it/s, loss=0.00462]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 14/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 15/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00518]   \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 15/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 16/50: 100%|██████████| 79/79 [00:11<00:00,  6.69it/s, loss=0.00485]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 16/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 17/50: 100%|██████████| 79/79 [00:04<00:00, 17.05it/s, loss=0.00734]   \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 17/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 18/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.00537]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 18/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 19/50: 100%|██████████| 79/79 [00:11<00:00,  6.74it/s, loss=0.00694]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 19/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 20/50: 100%|██████████| 79/79 [00:11<00:00,  6.75it/s, loss=0.00733]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 20/50 - Loss: 0.0051\n",
      "模型已保存到 ./checkpoints/2rf/miniunet_20.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 21/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.00554]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 21/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 22/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.0115] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 22/50 - Loss: 0.0055\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 23/50: 100%|██████████| 79/79 [00:18<00:00,  4.18it/s, loss=0.00459]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 23/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 24/50: 100%|██████████| 79/79 [00:04<00:00, 16.77it/s, loss=0.00975]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 24/50 - Loss: 0.0053\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 25/50: 100%|██████████| 79/79 [00:11<00:00,  6.72it/s, loss=0.00435]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 25/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 26/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00697]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 26/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 27/50: 100%|██████████| 79/79 [00:11<00:00,  6.69it/s, loss=0.00637]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 27/50 - Loss: 0.0053\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 28/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.00649]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 28/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 29/50: 100%|██████████| 79/79 [00:11<00:00,  6.74it/s, loss=0.00758]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 29/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 30/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.0059] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 30/50 - Loss: 0.0047\n",
      "模型已保存到 ./checkpoints/2rf/miniunet_30.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 31/50: 100%|██████████| 79/79 [00:18<00:00,  4.19it/s, loss=0.00574]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 31/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 32/50: 100%|██████████| 79/79 [00:04<00:00, 16.81it/s, loss=0.0154]    \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 32/50 - Loss: 0.0053\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 33/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00782]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 33/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 34/50: 100%|██████████| 79/79 [00:18<00:00,  4.19it/s, loss=0.00442]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 34/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 35/50: 100%|██████████| 79/79 [00:04<00:00, 16.79it/s, loss=0.00433]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 35/50 - Loss: 0.0048\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 36/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.00653]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 36/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 37/50: 100%|██████████| 79/79 [00:11<00:00,  6.74it/s, loss=0.00443]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 37/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 38/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.0056] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 38/50 - Loss: 0.0048\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 39/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.00921]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 39/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 40/50: 100%|██████████| 79/79 [00:11<00:00,  6.75it/s, loss=0.00609]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 40/50 - Loss: 0.0048\n",
      "模型已保存到 ./checkpoints/2rf/miniunet_40.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 41/50: 100%|██████████| 79/79 [00:11<00:00,  6.73it/s, loss=0.00355]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 41/50 - Loss: 0.0047\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 42/50: 100%|██████████| 79/79 [00:11<00:00,  6.72it/s, loss=0.00673]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 42/50 - Loss: 0.0048\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 43/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.00443]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 43/50 - Loss: 0.0049\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 44/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00563]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 44/50 - Loss: 0.0053\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 45/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.0114] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 45/50 - Loss: 0.0051\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 46/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.0559] \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 46/50 - Loss: 0.0056\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 47/50: 100%|██████████| 79/79 [00:11<00:00,  6.70it/s, loss=0.00567]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 47/50 - Loss: 0.0050\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 48/50: 100%|██████████| 79/79 [00:11<00:00,  6.71it/s, loss=0.00632]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 48/50 - Loss: 0.0052\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 49/50: 100%|██████████| 79/79 [00:18<00:00,  4.19it/s, loss=0.00455]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 49/50 - Loss: 0.0048\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Epoch 50/50: 100%|██████████| 79/79 [00:04<00:00, 17.03it/s, loss=0.00758]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 50/50 - Loss: 0.0049\n",
      "模型已保存到 ./checkpoints/2rf/miniunet_50.pth\n",
      "2-Rectified Flow训练完成！\n"
     ]
    }
   ],
   "source": [
    "# 训练2-Rectified Flow模型\n",
    "print(f\"开始训练2-Rectified Flow，总轮数: {epochs_2rf}\")\n",
    "\n",
    "for epoch in range(1, epochs_2rf + 1):\n",
    "    epoch_loss = 0.0\n",
    "    num_batches = 0\n",
    "    \n",
    "    pbar = tqdm(reflow_dataloader, desc=f'Epoch {epoch}/{epochs_2rf}')\n",
    "    for i, data in enumerate(pbar):\n",
    "        x_1 = data['img'].to(device)\n",
    "        x_0 = data['noise'].to(device)\n",
    "        \n",
    "        # 均匀采样[0, 1]的时间t\n",
    "        t = torch.rand(x_1.size(0)).to(device)\n",
    "        \n",
    "        # 生成flow\n",
    "        x_t, _ = rf.create_flow(x_1, t, x_0)\n",
    "        \n",
    "        optimizer_2rf.zero_grad()\n",
    "        \n",
    "        # 预测速度场\n",
    "        v_pred = model_2rf(x=x_t, t=t)\n",
    "        \n",
    "        # 计算损失\n",
    "        loss = rf.mse_loss(v_pred, x_1, x_0)\n",
    "        \n",
    "        loss.backward()\n",
    "        optimizer_2rf.step()\n",
    "        \n",
    "        # 记录损失\n",
    "        epoch_loss += loss.item()\n",
    "        num_batches += 1\n",
    "        \n",
    "        # 更新进度条\n",
    "        pbar.set_postfix({'loss': loss.item()})\n",
    "    \n",
    "    # 计算平均损失\n",
    "    avg_loss = epoch_loss / num_batches\n",
    "    losses_history_2rf.append(avg_loss)\n",
    "    \n",
    "    # 更新学习率\n",
    "    scheduler_2rf.step()\n",
    "    \n",
    "    # 打印epoch信息\n",
    "    print(f\"Epoch {epoch}/{epochs_2rf} - Loss: {avg_loss:.4f}\")\n",
    "    \n",
    "    # 保存模型\n",
    "    if (epoch) % save_every == 0 or epoch == epochs_2rf:\n",
    "        torch.save({\n",
    "            'model': model_2rf.state_dict(),\n",
    "            'optimizer': optimizer_2rf.state_dict(),\n",
    "            'epoch': epoch,\n",
    "            'loss': avg_loss,\n",
    "            'losses_history': losses_history_2rf\n",
    "        }, f'./checkpoints/2rf/miniunet_{epoch}.pth')\n",
    "        print(f\"模型已保存到 ./checkpoints/2rf/miniunet_{epoch}.pth\")\n",
    "\n",
    "print(\"2-Rectified Flow训练完成！\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "41f49848",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1oAAAHTCAYAAAA+gmmnAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAdsVJREFUeJzt3Xl8VNX9//H3TGayko0kEEgCYYfIEpBNBAWV4IIFseWrFqv1h61rK6i0aJVFEZdKXVpR6q51gVa0BRRQFBFBkAAia1hCCFnJvmeW+/sjZCSGhECWmYTX8/HII7n3zpk5d/iQ5J1z7rkmwzAMAQAAAACajNndHQAAAACAtoagBQAAAABNjKAFAAAAAE2MoAUAAAAATYygBQAAAABNjKAFAAAAAE2MoAUAAAAATYygBQAAAABNjKAFAAAAAE2MoAUAQCtUVFSk77//vsa+I0eOqKysrNZjMzMzlZeXV2u/3W5XRUXFaZ9/165dysnJaVA/TvfcjXH8+HHt3r1bdru9SZ8XAFoSQQsAgFZo7ty5+tWvfqXy8nLXvuHDh+svf/lLrcfefPPN+utf/1pr/6pVqzRw4EAdOXKk1rGXXnpJw4YNU2VlZb39mD9/vn7961+7tnfu3CmLxXLaj6VLl572OY4ePaqdO3e6tj/77DMNHDiwxrkBQGtD0AKAVuDpp59W586dFRISosmTJys9Pb3BbW+99VaZTCaZTCZ5eXmpR48eevTRR932S+zYsWM1d+7cOo8fP35cV155pQICAhQWFqY33nijxvHk5GSZTCYlJyc3SX9MJpO++uqrBj32zTffdL2XP/949dVXazx27ty5Gjt2bJP08XQeeugh5efn629/+5trn5+fn2JjYyVJ3t7e+uyzzyRJPj4+8vHxqfUcb7zxhjp37uxqU1xcrIqKChmGodWrV2vWrFny9vaWJFVUVKi4uLjWc/j7+8vPz8+17e3tLYvFIrvdXuNj9OjRruf6uaVLl+riiy9WamqqJMlqtSowMFDt2rU7+zcGADyExd0dAADU75NPPtGf//xnPfHEE+rTp4/uvPNO3XTTTfryyy8b/Bzt27fXypUrVV5erg0bNujxxx9XamqqXn/99Sbt65tvvqnY2Nh6A8ZLL72koKCgOo/PnDlTxcXFWrFihbKzsxUQEFDjeKdOnbRp0yZ16tSpqbp91tauXVsrBPTo0aNF+xAWFqbZs2fr4MGDrn0+Pj6u9/bUcOXl5SWzuebfVrOzs7Vy5Up98cUXys/P1/HjxzV9+nRt2bJFXl5estvtuu+++3TfffdJkiorK3XJJZe4QmlaWpocDodKSkpUUVGhI0eOKCwsrNbrnKquY++++66uvfZaFRcXa9++fcrIyJDT6dS+fftcj3E6naqsrFR8fPzZvlUA4BYELQDwcIsXL9bll1+uP//5z5KqpmbNmzdPqampio6ObtBzWK1WjRw5UlLViFJeXp5eeuklvfzyy3WOMpyLN998U2PHjq03aMXFxdX7HImJiXrggQc0bty40x738fFxnYu7DB06VCEhIW7tgyQ9+OCDMplMrm2LxSIvLy9JVeHKarXW2favf/2rRo4cqTFjxmjRokWaP3++9u/fr44dO+rhhx9WYmKiPv300xptTr1mavbs2froo49ks9nkcDjUr18/vfbaa+rfv79sNpsmTpxYo+2uXbtOO4q6atUq7dq1S0ePHnW9ns1mU1lZWY1/Z7vdLovFovz8/Ia/QQDgRgQtAPBwBw4c0HXXXefajoyMlFQ1otDQoPVzw4YNU0VFhU6cOKHOnTs3ST+bis1mO+00N1QpKirSwoUL5efnJ5PJpN/+9reKioqSVDVidGrwqktiYqJeeOEFLV26VPv379czzzyjefPmKTg4WJWVlXr77be1aNGiWu0slp9+bXjrrbf01ltvae7cufrxxx/173//W5JUVlambdu2nfZ1u3btWmO7vLxcDzzwgG699dYao6uvvPKKHn30UWVmZp75DQEAD8U1WgDg4davX69HHnnEtb1jxw5JUpcuXWQYRq1rYU79qEtGRoZMJpPCw8MlVf1yfN9996ljx44KDQ3VDTfcUGvFuddee009e/aUv7+/hg4dqs8//9x1rPo6pfXr12vevHmu7dNdR3W6a7Sqr7symUw6evSofvvb37q2f66+a7Ryc3N1yy23KDQ0VB06dNCdd96p0tJS1/GSkhL99re/VWBgoGJiYvTBBx/U+R41p3fffVe9e/eWj4+Phg8frg0bNkiqCtUmk0nff/+9cnJyZDKZ9NBDD0mSLr30Uv3+97+XzWbT1q1b9f333+uRRx5RRkaG63mdTqdrRKs+2dnZKi8v11133aURI0YoOjpa9957rx544AH5+vrq+PHjuvnmm2WxWHTVVVc16JwcDofKyso0ZMgQDR48+LQfw4cPr9EmKSlJsbGxmjdvXo39eXl5taaMAkBrw4gWAHi4mJgY19f79u3T22+/rSlTpigyMlJfffVVnVPsJNVYTc5ut8swDG3fvl1/+9vfdNVVV7mmDd51111as2aNnnvuObVr106zZs3SlClTtH79eklVIwx33XWX/vznP+vyyy/X+++/r4kTJ2rHjh3q27evNm3a5HqeIUOGaPr06ZLU4Ouoqq+7kqTrrrtO06dP1zXXXHMW71KVX/7yl8rIyNCbb76piooK3XfffSotLdVbb70lSbr//vu1fPlyPf/88woODtYDDzxw1q8hVYWKU4PsqSM9Z/L222/r1ltv1QMPPKDLL79cr732mq644gp9++23GjJkiIKDg7Vnzx4VFRXpwgsv1A8//CBJ2rNnj6ZNm6b27dtr7dq1kqoC7qlTP+12e73TBauNHz9eycnJslgsiouL0+LFi2U2m/Xcc8/p+PHj6t69u5599lndd999SklJqfe5SkpK9P3336tXr15asmSJ/P399fLLL9dYiVCSPvzwQz3//PM19vn4+OjJJ59USUlJjeuxDh06JC8vrxr7pKr3vby8XAMGDGjSKa8A0BwIWgDQSqSlpemaa65Rx44d9fLLL0uSLrzwQm3durXONtXTAjMzM2v8Aj58+HD985//lFQ1QvTWW2/pww8/dE1RtNvtmjJlipKTkxUbG6vHHntMN998sxYsWCBJGjNmjAoLC3X06FH17dvXdS1NUFCQoqOjz/oaqlOvu/Lx8VGPHj3O+jnWr1+vL7/8Ulu2bNHgwYMlVb1nf/rTn7RkyRLZbDa99tpreuKJJ3TbbbdJqrp2bdKkSWf1OpJcI4HV0tPTXVM6z+TRRx/Vr3/9az399NOSqkLPoEGD9Pjjj2v58uW68MILtWfPHuXl5em6667Ta6+9phMnTujEiRMaOnRorec7ddSvqKio3oVGqpnNZnXu3FkTJ07U9OnTXc+7atUqffrpp9q9e7eKi4tls9lkGIZrNUJvb28FBgZKkp566im9/vrrOnDggHr37q0XXnhBl19+uUwmk3x8fNSuXTvdcsst8vLy0uuvvy4fH59ai2Hcc8892rBhg7y9vWucR3FxsRwOR60asNvtKi8v18GDB10rJQKApyJoAUArcPz4cY0bN06VlZVav369IiIi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dPfdd+uFF17Q3//+d6WlpalTp07q0aOHysrK9MEHH+ihhx7S008/rfXr1+v555/XH//4R1ffvv32W02cOFEBAQHKzc2Vt7e3goKC9Oyzz2r16tU6cuSIPvzwQ/3zn//U1q1b9f/+3//TX//61xZ+BwEATclkMDEcANCKVVZWqqCgQFar1TWSlZ2drQEDBigjI0N33HGHRo4cqVtvvVUhISHKyMhQSUmJhg0bpqVLl6qwsFDTpk3Txo0b1blzZ8XFxemLL75QbGzsaV8vMzNTF154oY4cOSKr1SpJ+vOf/6z169frm2++UVFRkUaPHq1rr71W8+bNc4U8wzA0ffp0ffbZZ7rllltUUFCgxx9/XK+++qqSkpK0ZMkSbdu2TTNnztT69etb6u0DADQTpg4CAFq1xMRE9enTR9HR0Xr88cclVYUas7nuH3EHDx5UVlaW7rnnHk2YMEEffvihVq1apW7duik7O1tXX321evbsedq2L7/8sm699VY9//zzmjVrlu677z698847euSRR5SamqqQkBB9+eWXWrdunYYOHSqbzabk5GQlJCTo6NGjuvXWW2W322UymfTAAw9o8eLFrufOz89XRERE075BAAC3IGgBAFq1kSNHKjc3Vw888IBrhMlut8tiqXt2/IgRI5SXl6chQ4Zo7ty5GjNmjKZNm6bw8HBt2rRJa9asUX5+fq12ycnJWrx4se69915Jkslk0l133aVPP/1Uy5Yt06effurav2HDBr3xxhuyWq3q0KGD4uPj9dFHH2nw4MH605/+pIcffliTJ09Wly5dtH//fklVKydGRkY28TsEAHAHrtECALQZXl5ekqTi4mK1a9eu3sfef//9+vrrr/WXv/xFixcv1p49e5SUlKRf//rXstlsys/P16BBg1RUVKRXXnlF48eP16FDh5SVlaUhQ4bIbrfL4XBo7dq1SkxMlLe3t3x8fLRx40ZNnDhRa9eu1dChQyVJFotFTz31lDZt2qSZM2fq0KFDslqtuvbaa3XNNddo8uTJ2r9/v/bs2aNevXo1+/sEAGh+jGgBANqc9PT0M07BKy4uVpcuXbRz504FBQVp7ty5Sk9P16ZNm7R69WqFhIRo586dOnjwoMaPHy9Juuyyy1RQUKDjx49r9uzZmj59uhITEyVVjWK9/fbbuummm/T666+7QpYk3XLLLeratavGjx+v8vJy9erVSz4+Plq3bp3MZrOuuOIKvffee/ruu+80ePDg5ntjAAAthhEtAECbUV5ervnz56tDhw7q3r17vY99/fXXJVUtprFr1y4ZhqHFixfrf//7n95//31J0jfffKMHHnhA33zzjSwWi0wmk7y9vZWamqr09HTt27dPzz//vH75y19KkmJiYvTxxx8rODi4xmu9//77Kioq0qBBg7RlyxZZLBYNGDBAo0ePliRdd911GjlypEwmk0aOHNnUbwsAwA0Y0QIAtAl2u11///vfVVRUpC+++EKjRo2SVHW/LKfT6XqM0+lUdna2brvtNg0bNkzR0dGaNWuWtmzZomeeeUb/+Mc/XFMQR40aJafTqaefflqS9MorrygsLEyTJk3Sp59+qrS0NFVUVCgwMFBS1YhXdcjKzs7WqQv77t27V3369NEVV1yhCRMmaODAgSorK5Mkde7cWQEBAbr00ktdqxQCAFo3ghYAoE3YvHmzxo0bp9tvv12ffvqpJk+eLOmnGxGf+nVYWJhiYmL00ksvKSMjQ0uWLNEdd9yhv/3tbwoKCtK///1vBQQEyGw26+9//7veeustlZWV6bbbblNhYaG2bdumW2+9VWPHjtWsWbMUFBQkk8nkuvmxJP31r3/VnXfe6doePny43n33XQ0cOFB+fn4qKCjQLbfcoqysLF177bXq0qWLVq1apSVLlrTo+wYAaB5MHQQAtAmPPPKI4uPj9ec//1m33Xab6xqtN9980/WY6qBlNps1b9481/7OnTvrhRde0OTJk7Vr1y7Nnz9ff/rTnyRVBaS9e/fWWi6+srJS5eXlru0hQ4ZoxowZevrpp+V0OlVeXq5Vq1ZJkjZt2qQlS5boiy++0J133qnXX39dXl5e+tOf/qSePXvq1ltv1aJFi/TFF1/ouuuu0+7du/X8888311sFAGgB3LAYANDmnGl595a2bds2ffvtt7r55psVEhLi2r9q1SqFhIS4pjlK0s6dOxUWFqbo6Gg39BQA0FQIWgAAAADQxLhGCwAAAACaGEELAAAAAJoYQQsAAAAAmhhBCwAAAACaGEELAAAAAJoYQQsAAAAAmhhBCwAAAACaGEELAAAAAJrY/wduCt9BN0PA+QAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1000x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制2-Rectified Flow损失曲线\n",
    "plt.figure(figsize=(10, 5))\n",
    "plt.plot(losses_history_2rf)\n",
    "plt.xlabel('训练轮数')\n",
    "plt.ylabel('损失')\n",
    "plt.title('2-Rectified Flow训练损失')\n",
    "plt.grid(True)\n",
    "plt.savefig('./results/2rf/loss_curve.png', dpi=600)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "39fa8772",
   "metadata": {},
   "source": [
    "## 7.使用2-rectified flow推理测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f37426ea",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2-Rectified Flow推理函数\n",
    "def infer_2rf(model, rf, num_samples=10, steps=5, save_path='./results/2rf'):\n",
    "    \"\"\"2-Rectified Flow推理函数\n",
    "    \n",
    "    Args:\n",
    "        model: 训练好的模型\n",
    "        rf: RectifiedFlow实例\n",
    "        num_samples: 生成样本数量\n",
    "        steps: 采样步数\n",
    "        save_path: 保存路径\n",
    "    \"\"\"\n",
    "    model.eval()\n",
    "    os.makedirs(save_path, exist_ok=True)\n",
    "    \n",
    "    generated_images = []\n",
    "    \n",
    "    # 设置模型引用到RectifiedFlow\n",
    "    rf.set_model(model)\n",
    "    \n",
    "    with torch.no_grad():\n",
    "        pbar = tqdm(range(num_samples), desc=f'生成2-RF样本 (步数: {steps})')\n",
    "        for i in pbar:\n",
    "            # 初始噪声\n",
    "            x_0 = torch.randn(1, 1, img_size, img_size).to(device)\n",
    "            \n",
    "            # 使用torchdiffeq进行ODE求解\n",
    "            t_span = torch.linspace(0, 1, steps).to(device)\n",
    "            trajectory = odeint(rf.vector_field, x_0, t_span, method='euler')\n",
    "            x_t = trajectory[-1]  # 取最后一个时间点的结果\n",
    "\n",
    "            # 保存生成的图像\n",
    "            raw = x_t[0, 0].cpu().numpy()  # (28,28)\n",
    "            # 归一化到 0-255（防止值域异常）\n",
    "            norm = (raw - raw.min()) / (raw.max() - raw.min() + 1e-8)\n",
    "            img_uint8 = (norm * 255).astype(np.uint8)\n",
    "            cv2.imwrite(os.path.join(save_path, f'gen_{i}.png'), img_uint8)\n",
    "            generated_images.append(x_t[0].cpu())\n",
    "            \n",
    "            # 更新进度条\n",
    "            pbar.set_postfix({'样本': f'{i+1}/{num_samples}'})\n",
    "    \n",
    "    return torch.stack(generated_images)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "dce86ae8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "运行2-Rectified Flow推理...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "生成2-RF样本 (步数: 5): 100%|██████████| 20/20 [00:00<00:00, 59.01it/s, 样本=20/20]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "生成了 20 张图像\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "source": [
    "# 运行2-Rectified Flow推理并生成图像\n",
    "print(\"运行2-Rectified Flow推理...\")\n",
    "generated_images_2rf = infer_2rf(model_2rf, rf, num_samples=20, steps=sampling_steps_2rf)\n",
    "print(f\"生成了 {len(generated_images_2rf)} 张图像\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc9ce574",
   "metadata": {},
   "source": [
    "## 8.计算两模型的IS和FID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "3bd004fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 计算IS和FID指标\n",
    "def calculate_metrics(generated_images, real_images, device):\n",
    "    \"\"\"计算IS和FID指标\n",
    "    \n",
    "    Args:\n",
    "        generated_images: 生成的图像张量，[N, C, H, W]\n",
    "        real_images: 真实图像张量，[N, C, H, W]\n",
    "        device: 计算设备\n",
    "    \n",
    "    Returns:\n",
    "        is_mean, is_std: Inception Score的均值和标准差\n",
    "        fid: Frechet Inception Distance\n",
    "    \"\"\"\n",
    "\n",
    "    inception = InceptionScore().to(device)\n",
    "    fid = FrechetInceptionDistance().to(device)\n",
    "\n",
    "    # 转换为3通道\n",
    "    generated_3ch = generated_images.repeat(1, 3, 1, 1)\n",
    "    real_3ch = real_images.repeat(1, 3, 1, 1)\n",
    "\n",
    "    # 如果原始范围是任意实数，先压到[0,1]再乘255\n",
    "    gen_min, gen_max = generated_3ch.min(), generated_3ch.max()\n",
    "    if (gen_max - gen_min) > 1e-8:\n",
    "        generated_3ch = (generated_3ch - gen_min) / (gen_max - gen_min)\n",
    "    real_min, real_max = real_3ch.min(), real_3ch.max()\n",
    "    if (real_max - real_min) > 1e-8:\n",
    "        real_3ch = (real_3ch - real_min) / (real_max - real_min)\n",
    "\n",
    "    # 转 uint8 后放到 device\n",
    "    generated_3ch = (generated_3ch * 255).clamp(0, 255).to(torch.uint8).to(device)\n",
    "    real_3ch = (real_3ch * 255).clamp(0, 255).to(torch.uint8).to(device)\n",
    "\n",
    "    # IS\n",
    "    inception.update(generated_3ch)\n",
    "    is_mean, is_std = inception.compute()\n",
    "\n",
    "    # FID\n",
    "    fid.update(generated_3ch, real=False)\n",
    "    fid.update(real_3ch, real=True)\n",
    "    fid_score = fid.compute()\n",
    "\n",
    "    return is_mean.item(), is_std.item(), fid_score.item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "97e7683a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "加载真实MNIST图像用于计算指标...\n",
      "加载了 1000 张真实图像\n"
     ]
    }
   ],
   "source": [
    "# 加载真实MNIST图像用于计算指标\n",
    "print(\"加载真实MNIST图像用于计算指标...\")\n",
    "transform_eval = transforms.ToTensor()\n",
    "real_dataset = datasets.MNIST(root=data_root, train=False, download=True, transform=transform_eval)\n",
    "real_dataloader = DataLoader(real_dataset, batch_size=batch_size, shuffle=False)\n",
    "real_images = []\n",
    "for imgs, _ in real_dataloader:\n",
    "    real_images.append(imgs)\n",
    "    if len(real_images) * batch_size >= num_samples:\n",
    "        break\n",
    "real_images = torch.cat(real_images, dim=0)[:num_samples]\n",
    "print(f\"加载了 {len(real_images)} 张真实图像\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "a954bd4e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "计算1-Rectified Flow的IS和FID指标...\n",
      "1-Rectified Flow - IS: 1.2584 ± 0.1297, FID: 88.4659\n"
     ]
    }
   ],
   "source": [
    "# 计算1-Rectified Flow的IS和FID指标\n",
    "print(\"计算1-Rectified Flow的IS和FID指标...\")\n",
    "is_mean_1rf, is_std_1rf, fid_1rf = calculate_metrics(generated_images_1rf, real_images, device)\n",
    "print(f\"1-Rectified Flow - IS: {is_mean_1rf:.4f} ± {is_std_1rf:.4f}, FID: {fid_1rf:.4f}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "099b0e4f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "计算2-Rectified Flow的IS和FID指标...\n",
      "2-Rectified Flow - IS: 1.2187 ± 0.1048, FID: 106.1152\n"
     ]
    }
   ],
   "source": [
    "# 计算2-Rectified Flow的IS和FID指标\n",
    "print(\"计算2-Rectified Flow的IS和FID指标...\")\n",
    "is_mean_2rf, is_std_2rf, fid_2rf = calculate_metrics(generated_images_2rf, real_images, device)\n",
    "print(f\"2-Rectified Flow - IS: {is_mean_2rf:.4f} ± {is_std_2rf:.4f}, FID: {fid_2rf:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a09d95d",
   "metadata": {},
   "source": [
    "## 9.可视化生成结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "681f83a3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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0KHBxrF06VJR0/Y7r1GjRqLja/suonA6/fTTTf20/UOfffbZwKNBcdG1a1dRO//880XN3wt22bJlGRsTMuujjz4SNW39OeeccyJtbe3R9s/X9j/X3HPPPZH2XnvtJfqcfPLJpufUrpsQT9tz+o033oi0X3vtNdGnZEl5S61BgwaiZs3zyCQ/u8g5fZ736dNH1O69996MjAn57+abbxa1pPvgX3755aIW8jdDNir4bzIAAAAAAAAAAFmKm+gAAAAAAAAAAMTgJjoAAAAAAAAAADG4iQ4AAAAAAAAAQAyCRRPQArduv/12UVu9enWk3bdv34yNCeHccMMNiR979dVXR9pr165NdzjAdo0aNTL1W7FiRYZHAjg3evRoUWvatGmw4//888+R9ueffx7s2MXVzJkzRe2MM84QtZYtW4ra7rvvHmwcb731lqnfyy+/HGmfe+65psdt2LBhh8eE7LDLLrtE2n6IX5z58+eL2qRJk4KMCcXP8ccfb+o3cuTISHvy5MmZGA4KiBY2qtVC8s9ffrClc3qw6FFHHSVq1apVi7SXL1+e5uiKtq1bt4qafx7Zc889Tcc65phjRK1UqVKidtddd0XarVu3Nh0/JC1g/sADD8z3cSAzLr30UlHTgmO1gFzN9OnTI+3hw4cnG1ghxl+iAwAAAAAAAAAQg5voAAAAAAAAAADE4CY6AAAAAAAAAAAxuIkOAAAAAAAAAEAMgkXzUL16dVF74oknRK1EiRKi5oeuff311+EGhqzkB7hs3rw56PFXrVqV5/G10JLKlSvneewqVaqIWjohq344S69evUSf9evXJz5+cXTSSSeZ+r3//vsZHgnyixb2s9NOtv/+bQlGe+6550StXr16puNr49i2bZvpsRadOnUKdizsmKlTp5pqmfb7778nelzz5s1Fbdq0aekOB/ng0EMPjbSt690777yTgdGguNLOn+vWrRO1hx9+OD+Gg2Js2LBhoqYFi5555pmidvXVV0faffv2DTcw/KOPP/7Y1M8PcteCRbds2SJqL774oqg9//zzonbddddF2tawbhRebdq0ibS181SFChVMx1q7dq2oXX755ZH2xo0bd2B0RQN/iQ4AAAAAAAAAQAxuogMAAAAAAAAAEIOb6AAAAAAAAAAAxOAmOgAAAAAAAAAAMQgW/R9aOOiYMWNEbddddxW12bNni9rtt98e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7RhtjdIyEzT+uevUU08NMaSsUth/6/nnKef0tX6//fYTtS+++ELUnnzyyUhby2jQrqfTeR8ttPfaz+YaPHiw6KOtndpYTzrpJFH74IMPdmSI/3h8i5B7omvvl5bN8sQTT+T5OC0bTzu3W37fWH8DJe2nPe7rr78Wtccee0zUhg8fnufzFYR09kTXPrtseV0+7bO78MILRe3555/P83HPPPNMno9zzrkqVark2a9Bgwaij7bGar8ltWvlbMCe6AAAAAAAAAAAJMRNdAAAAAAAAAAAYnATHQAAAAAAAACAGNxEBwAAAAAAAAAgRrEJFtVCRV599dVIu127dqKP9vZ89tlnotanTx9RW7hwYaSthRedc845ota4cWNR80Mf69SpI/poIW+ZDmYr7GEz6Wjbtq2ojR8/PtIuUaKE6VgzZswQtfvvv1/UXnvttUhbC1ipWbOmqN16662i5ofNaHNKe9yDDz4oaiEDOIprIFapUqVE7bbbbou0tYA7LRDFGpLi1z7++GPRp2/fvqI2efJkUfMDKwsiQMnyGtN9jmxVqVIlUZs0aZKo+d/zMWPGiD4dOnQQtYoVK4qaFgZTvnz5fxync/r7unr1alF76623Im1tPVqyZEmezxdacVijtDVEC5++/fbbI+2qVauajm/9/vrj2Lx5s+ijhRdVrlxZ1Nq3b28am88a/OkHcx1++OGmxxWXNSqp008/XdSGDRsmatp7MWjQIFHzg0WLouKwRiWlrW2jRo0StY4dO5qOd+edd0ba2jVTYVfY16gyZcqI2kEHHSRq/n0B55yrV69ensefN2+eqL399tui9u2334qadj29ePHiSFv7rdesWTNR69Gjh6j5QbcVKlQQfbTPSBurdm24atUqUbPI1mDR/v37i9q1114baW/dulX00e7xfP7556LWokULUTvwwAP/cZw7wvJ9s34ntevyXXbZJdLesGGDbWAZVhSDRXfffXdRGzhwoKhpa5kfFvzII4+IPtq9S+0aW3PYYYdF2hMmTBB9tHmm3e86+uijI+2C+F2nIVgUAAAAAAAAAICEuIkOAAAAAAAAAEAMbqIDAAAAAAAAABCDm+gAAAAAAAAAAMQoksGiDRs2FLUXX3xR1I466qhIWwtJe+mll0StV69eorZ+/fo8x5U0SMs5GWZ66KGHij6dOnUStZEjR+Y5rnQU9rAZKy20Yfjw4aLmB9Bo74/2up988klR84NM4o5nOb5WO+CAAyJtLQCldOnSorb33nuL2i+//CJqSedGcQjE0sJf/dBY5+Qapb1GLUzFGrzjrzVagJ62Hv3xxx+iNnbs2Eh75syZos/cuXNFTZt32mtauXJlpG39bllDATWFaU5VqVJF1JYuXSpqftixFlLz/PPPi9qmTZtEbe3ataJ2zDHHRNra2tm8eXNR09YVPyx1+vTpoo8WEqgFYoVU1NYobVyPPfaYqGmhZVogctLn/PXXX0XND5DU+gwdOlTUtPA0Pyjw8ssvF320gHnrGuK/JmuweHG5jkrqsssuE7UBAwaImvZePProo6J2ww03hBlYFitqa1RI++23n6h9//33oqZ9f7VrEz9A2A8YLgqK4hqljevII48UtQsvvFDUunXrlug5tfdRC9Hzr320YFTt2txyn0Ebw/z580XtuOOOEzXtt15SSeeUds0Rcr07/vjjRe2OO+6ItP3fO87JgOE4/mfrnAzrrF27tuijXTfXqlVL1C644AJR839zamub9T289NJLI+3BgwebHpdp6QSLZsMapY3hyy+/FDXtN9Xjjz8uav5vtltvvVX0Cfn7+LzzzhN97rvvPlHTgponTZoUabdt21b0SefzTYpgUQAAAAAAAAAAEuImOgAAAAAAAAAAMbiJDgAAAAAAAABADG6iAwAAAAAAAAAQw5Y+l8W0jfivv/56UfMD+pyTG8b37t1b9HniiSfSGN0/P59zzu28886ipoUO7r///nkeSwvSQhgnnniiqNWtWzfPxy1cuFDUtNC++++/X9RCBnNqNT9IacSIEaLPWWedJWpa2O5hhx0malu3bv2nYRZrWrCGFmjnr29ayIgWQKsFwmrztWzZspG2FiSkhYU0atRI1Lp37y5qPm293rhxo6hpgUk1atSItLVQy+LMDyZyTv8ObtiwIdLWAmm0UFir//znP//Yds653XffXdS0MFB/vjRr1kz00eYPdsyxxx4raldccYWoaYHFftBnkyZNRJ8ZM2aI2l9//WWq3XXXXaLm00KytGu+iy++ONLWQuSs508t5FYLKkX66tevn/ixWoibv66kE5qIwkdbG6whwD/99JOoFcUg0eJA+95PmDBB1D777DNR8wOL99xzT9FH+/108skni5oWCv/HH39E2lOmTBF9DjzwQFHTxuG/zuHDh4s+99xzj6iFDBENKeR6rR3rgw8+ELVPP/000l6/fn3ica1atUrUVq9eHWn//PPPos/48eNNx9dCt88888xI2w9Kdc658uXLi5r2mg499NBIuyCCRbMhCDQ07Xe19ptHe+0vv/yyqP3www+RdujrHP94Q4YMEX20a38tgPeAAw6ItLXw1C+++ELULEHKmcRfogMAAAAAAAAAEIOb6AAAAAAAAAAAxOAmOgAAAAAAAAAAMbiJDgAAAAAAAABADHOwaEFv3h7n9NNPF7Urr7xS1LZt2yZqTz/9dKT91FNPhRuYomXLlqKmhTk2aNBA1PzQGy2wcs6cOYnHVhRp4YR16tSJtJcsWSL6bNmyRdRKlSolapZgCy3Yr3///qJWEOF4/vf3oosuEn2aNm0qaq1atRK10047TdTefPPNNEZXtJ199tmipq2nfmCLtrb5QZHpeP3110WtT58+ouYHHTvn3DnnnBNpawHJ/vfPOT34beXKlaLmh96sWbNG9CmKYTMa7XXedNNNoqYFzPbs2TPSTidE1EILEX3//fdFrWrVqqK2adOmSPuWW24RffzwHPwzbe706tVL1LTzp+bcc8+NtP2AIOece+WVV0RNW7e0sfmB6VpYmz+nnXNut912EzX/NWlrrnb+f+ihh0Stb9++okbIbWbsvffeiR+rBcCheNOuOay/Z7XfcSjatN9xP/74Y6StXYe89dZbopb0vsmFF14oal27dhU17Rzqn6ueeOIJ0Wf58uWJxlUUaZ/R2rVr8/05k/r7779FzQ+e1H6zt2nTRtS0+fT777+nMbodl633H9Plv6527dqJPtq5Snv/td9x2fAeff/996J2zTXXiJofzq1d53/55ZeiVtCvkb9EBwAAAAAAAAAgBjfRAQAAAAAAAACIwU10AAAAAAAAAABimPdEL+h9Z5xzrn79+qJ29913i5q2f/Xq1atF7cYbb4y0tX3T01GtWrVI+9lnnxV9GjVqZDrWa6+9Fmn369dP9Jk2bdoOjK7oq127tqi98MILkba2r6m/N5Nzzg0cOFDU/PnjnHMlS0a/Uo8//rjos27dOjnYLJCbmytqt99+u6hp+xnXqFEjI2MqCrS9hbW95rV9F/01Q/uMQtLWeW1/Pa02evToPI9ftmxZUdP2Edb28vZfe3HZ/1xz5JFHipq2h5x1n85M6t69u6hp83/z5s2idscdd0Tajz32WLBxFVfad1z7vlldeumlkbaWLaOtW9r398477xS1E088MdLW8hisa4G/r+lXX30l+mj7xWprWzZcExcXO++8s6mf9plMnjzZ1A/Fx2+//VbQQ0AhZ1lD0lln/EwhLbfEz0pzTr++u//++yNtP2sGRYs27/zrKC2ryGrZsmWJH5tEcTlfX3HFFaKmXdt+9NFHopateTzaZzd37lxR83MeO3fuLPo8+uijopbf+/P7+Et0AAAAAAAAAABicBMdAAAAAAAAAIAY3EQHAAAAAAAAACAGN9EBAAAAAAAAAIhhDhbNBtWrVxe1Zs2amR7rh18559yWLVsSjUML82jQoIGonX322ZF269atTcdfs2aNqH3wwQeRNiGiedPmRocOHSLtp59+2nSs+fPni9rVV18tahs2bIi0tZCXwhSSYf2OnHHGGaI2YMCA0MPJeloIyLHHHitqfsiLc3oAqR+i16lTJ9HHn3POOffQQw+JWtJQUut8tfRbv3696Vjaa/LfW+35imLYqPaa+vTpI2plypQRtfHjx4uaFgob0p577hlpX3LJJabHjRw5UtT69+8faRemtbMw0cJAtfXooIMOEjU/OFYLiB0+fLiodenSxVSrU6dOpK3NAa2mhS+9+OKLkfawYcNMx0LB0oLLtXVR++yOOOIIUXv55ZfzfByKrnr16oma9dph0qRJoYeDYq58+fKiNmbMmEhbC2Nft26dqGnhhASJFg3Wc57W7+KLL460q1WrZnrOKVOmiNp7772X5+OsY02qKPzWa9KkSaS92267iT5aCKcWsFmYaPNg4sSJkfbll18u+vj375wr+PtM/CU6AAAAAAAAAAAxuIkOAAAAAAAAAEAMbqIDAAAAAAAAABCDm+gAAAAAAAAAAMQoVMGilSpVEjVrUMHOO++cZ5+KFSuKWosWLUTtzDPPFLVrrrkm0di0YJBjjjlG1L7//vs8j4WoE044QdT8z+Svv/4SfbTAiq1bt4rac889l8boCgctrFCb148//nh+DCfrWMJN2rRpI2paOLH2vj755JORtjZf/eA955w75ZRTRO3ggw8WNW1eZ4OkoTFFMSCuSpUqonbUUUeJ2tKlS0WtX79+mRjSdtrn9O9//zvS1gKM/vjjD1G77777RG3btm1pjA5Wb7zxhqhp82n06NGiVrJk9DLyoosuEn2uvPJKUbN+x/3v9OLFi0WfW265RdSGDh0qagSsFQ7++VELmrau9atXrw4yJhQdWkij1euvvx5wJMgU/7pj1apVok/I699mzZqJ2syZM0WtbNmyovbWW2+JWsuWLSNtLWBw3333FbU1a9b80zCLhEyHVmYra4iodm/i0EMPTfScWvj6kiVL8nxccfg80lWrVq1Iu3r16qLPggULRG3+/PmiVtjf7xtvvDHSbteuneijrXcFjb9EBwAAAAAAAAAgBjfRAQAAAAAAAACIwU10AAAAAAAAAABicBMdAAAAAAAAAIAYhSpYVAvkWLFihahpQWbPP/+8qPlhVFr4aNWqVUWtfPny/zjO//IDH7SQNC2ESwsRLeyhAZmmhWscd9xxefabNWuW6FNc32stRFQLMJw9e7aovf/++xkZU2Fz3XXXiVrv3r1FTZtjGzduFLWjjz460p46daroc/7554vaM888I2r/+te/RO3RRx8VtUyyBgIl/Q4mDSTNZocffrioaeeS/v37i5olAMhqp53kf3Pv06ePqJ188smR9ubNm0Wfm2++WdQIz84un3zyiah17NhR1EaOHBlpV6hQQfTRAty076oWAukHW1111VWijzbHUHj565t2bW61cuVKUSuu13j4f7Rga+ZE4VW3bl1RGzNmTKStBWX//PPPovbTTz+J2o8//ihqW7ZsibTHjRsn+mjB7nvuuaeoaefVdevWRdrdunUTfYpDiKimuH5XtWumOnXqiFrnzp3zfKz2Hmohoo8//vgOjDD/FIU5oP3m92nXPpUqVRI1f71wLnvfI20e++vpqFGjRB/tt3DJkvI2tn+sTOIv0QEAAAAAAAAAiMFNdAAAAAAAAAAAYnATHQAAAAAAAACAGNxEBwAAAAAAAAAgRqEKFv32229FTQu/Ou2000StRIkSoqYFfPg2bdokal988YWoaRve+5vb33HHHaLP8OHDRS1bwwAKGy2QwQ80aN68uejz9ddfZ2xM2cR/L+655x7R59JLLxU1LaRXC47Lb9bQykzSgoS04Iu1a9eK2hFHHCFq06dPj7S193nQoEGi9tRTT4las2bNRM2X6fcwnWNZgnGKAv91jh8/XvSpX7++qGkhoiHfo1122UXU7rrrrjyfU+vz9ttvhxoWMqRJkyai9uKLL4pa6dKlI20t9FZbV7S1rEePHqKmhV2haPPXkGXLliU+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xqLm69u3r6jdddddeT4umxX266hMK1++vKhp572jjz7adLyrrroq0h4wYECygWWxwrRGZQMtwO2ZZ54xPdYPevPDkJ1zLjc3N9nAskRxWaO0ewXvvvuuqPnX2D///LPo06ZNG1HbsGFDGqMrWpLOKT/UNbSyZcuK2ujRoyNt7fvcvn37xM/pf0e090arPfHEE6KmXatv2bIl0bj8EFHnnKtevXqk7Qd1O6f/7sr0PbCkr9G57F2jrOOqUqWKqPm/7bTA6z322EPUtM9ECz2dPXt2pK1d+59//vl5Pi7uOfOb9l7ndf+Av0QHAAAAAAAAACAGN9EBAAAAAAAAAIjBTXQAAAAAAAAAAGJwEx0AAAAAAAAAgBhFMli0UqVKojZjxgxRq127dqStvcZFixaJWosWLURt2bJlouaHX6QTepCtimLYTMuWLUXt9ttvF7XOnTuLWtLXpD1Omy9+MIQWIJJUtgTfFrVArHTeV/+x77zzjujTqVMnUdPWO23dSid0MxslCQbZ0eMVJlqI8Ycffhhpr169WvTRQmi1cMjiqjCtUaVKlYq0L730UtHnhBNOELUjjjhC1LSARy1810J7nBaA/dprr0XavXr1En2067TCpCheR2Vax44dRW3w4MGi9ssvv4ja6aefHmkX9vmjKUxrVDbww/Kc09dKrd/cuXMjbS2QNBuC09JRFNeoihUripp/vnHOuRNPPFHUlixZEml36NBB9Jk6dWrywRUD2Rosqs3Xnj17Rtr33HOP6XFJf//51+nOOdenTx9R++mnn0QtG37XFcT9hKIYLBqSdX5qQn522XouJFgUAAAAAAAAAICAuIkOAAAAAAAAAEAMbqIDAAAAAAAAABCDm+gAAAAAAAAAAMQoksGip556qqgNGzZM1CyBWC+88IKoXXbZZYnGlS3BjSEVxbAZjTbWY489VtSuvPLKSFsL9pswYYKoffLJJ6L26aefitrkyZMj7cI+fzTFIRDLuhYceeSRkbY2T7Qwvvbt24vaF198kedzskZFFfY59dRTT4mav0a99NJLos9FF10UbFxFUVFbo7RxlS1bVtR22203UWvVqlWej9OutebNmydq06dPF7U///wz0t66davoU9gVlzUK+aeorVEoWIV9jdLGcNttt4la3759RW39+vWidskll0Ta2j0G/LNsDRbV+CG0N954o+hz7bXX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GOY90bW9dJLue2Xd18myT7fG2q9169aR9kEHHWR6nLb/eb9+/URt/vz5eR7Lutem//5Y92qy7uto2Tc19F6MSfddT2dv7ZD7AVr299KOr32XhgwZImranlA//vhjpG3dy9ayV26m99vO9D552hqivT9J9xi1fCese4Jp+xv6e9Y559y8efMi7TVr1og+2l6b1r1n/X3xBgwYIPqcdtpppuf090z78MMPRZ+uXbuKmmU90hTE3rDO2eaBda6H3K93+PDhoqbt32pZ36x7z2n76fm08Wv7h7Zr107U/Ply1llniT5adoR1/vvvhfYaLXPRKp29oy3HsozV+t5oxy9Tpoyo3XbbbZG2lqtwxRVXiNp3330napYMi3S+90n3mreyfG6hz4NJr9XS2a/dfw3W/fO1fVirVq0qasuWLYu0169fL/pY52zS70nInJ105HcWiPW3nmWPYOu4LN8J7bylZShoc/H666+PtG+99VbR55577hG1pUuXito111wjav41XvXq1UWfJ554QtS0LAfLb4ike+I6Z7vuD3nOi2PJbbBcvzuXfL2z/ma49NJLRc3f1/qtt94SfS666CJR0z5z7Zy5du3aSFtbJ62/2fzXaf18recDS85BQV2v58V6D8B/z7R18rfffhO1Rx99VNR69eqV52OTnn+cs82BnXfeWfS59tprRU275vZZv6fWfcHzYw/0TD5n0v3PrazfJX+OallmzZo1E7ULL7xQ1LTP2F+TZsyYIfpo58IaNWqImn9PwV//nJP3v+KeU8s38dcoLVMnSbYSf4kOAAAAAAAAAEAMbqIDAAAAAAAAABCDm+gAAAAAAAAAAMTgJjoAAAAAAAAAADHMwaKWYBnnbJvzWwMHMh1q6IccaaFHlvAT55x79dVXRc0PPNNCB5OGZCYNZ3UubEhsOpLOKWuoQtIgE+v7qPHDFVu2bGl6nB+k5ZwefLBu3bpI2zo/NZbAqnRCrPzHWkLj0pHpECKNH6zxyiuviD6HHHKIqPnzxDl9jvmvSZsTo0aNErXnnntO1LSQrDFjxkTaNWvWFH20sA1tDfHttddeolanTh1RW7BgQZ7H0uRH+LHG8hzpBH/5tLmihaBp73dI2li1eeCPd+PGjaKP9l3VjuWHfU+ePFn0ufHGG0VtxIgRopb0cwt5bsz0ehT6sb4uXbqImv+a/KBR55z7/vvv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xuuHJJ566qmijx9a7Zxz5513nqhpQTXa3PBZz/dagO3PP/8caffs2VP00c6hfoioc8nDX6znFssaFZJ1DbR8lzIdJqidk+666648j9WxY0dRe/3110XtxRdfFLW//vpL1C666KJI2/q6LWuINaDdevyCkDTQMXQYmIX2nFro+eTJkyNtLYC5SpUqouYHhjrn3KZNm0TNcj2d6TBfTUE8p2UMSWnrt3betrC+NyGvMx955BFRO+WUU0TNn5/W0D7L+qP1sf5u1OR3mPaO8APztOujQw45RNQ+/vhjUfOvfbQA48WLF4uadg7S7j34IcY//PCD6OOHuDvn3LfffitqH330kaglXXeTBnimc38iW9co/7ujrUeW+y3OJf99Yz2n+q/J+nmsXLlS1J588klRq127dqStzU3tXKmxXDenE7yaNLwzNMt1gfbatdep/VbyP6eWLVuKPlpg8dlnny1q2n0ff83TXo+2HvnX3M7p66JP+5yS3udLZ01JGoab5FzIX6IDAAAAAAAAABCDm+gAAAAAAAAAAMTgJjoAAAAAAAAAADG4iQ4AAAAAAAAAQIyclHEn9XLlyomaJaAsnRBIS3CDdiwtQEQLOfBr1hDOpOE/6RwraYhr0s35rYGwWhiclTanLAESSYNTtMdaAytCBj6lE9ZiCQWyhk/674X1cUkDjDTa+LVAOwstKMWy1mhj0I7VoEEDUfPDHIcOHSr6PPzww6L2wAMPiJoWSurPFWt4sGbYsGGidtJJJ0XaN910k+jz9NNPi5ol9CZpoEjc8S1zX6tZw3I0ZcqUETVLOI51jbIEsWjvhbYWayHbV111lagdcMABkfasWbNEn7lz55pqQ4YMETUtrMuXNLA4nVDJpI/TatbwZp92bRJynbecW5KGmzqnz33/HKGtndbQWO174/fTAppChv1aw5Es77X2OO1aVHtNVlpgoWW+WK+5QwYPasfS5oEfgnbdddeJPr179xY17X1M+pqSvj/W703IQFhN0jm18847i1rS+aSxrD/phByG/Gw1LVq0ELU///wz0l6zZo3oY/08/LkS8n3VatbjJ70ud06/jtI+z65du0baX331leizcOFCUbO8t9bfLUkDl7U+1t91lqBJjfVYlrkd8trKOheThgxr11Eh738kfVw69wmSvq8a7RrMD0QeNWqU6OOH5VrHZX3vQ56LNelcR2n3o5Je+yS9R7LXXnuJPlrIp3bNp62x/u8U7R7DG2+8IWrWc2HIkOqkv3k0SR+rzeO8fuvxl+gAAAAAAAAAAMTgJjoAAAAAAAAAADG4iQ4AAAAAAAAAQAxuogMAAAAAAAAAEMMcLGoNxLIExGiSbgRvDUPUWELLrOMPGeilSRp0kZQW+JE0/CSONQgyv8MLQgZuZTq8K53jhwwMs7CG4CQN7dOCNazj8FmD9vyAR23tKV++vKhpQXuZDoNr06aNqO22226R9ieffCL6LFq0KM9xWceaTpCy//5bH5dOIJb22VnWwXRCqpOel7RxaTU/lEYL47GGmVrOtdb5mc75MZO0ca1fvz7RsazXUZa5bpU0sMf63vtzPen1l3Vs1u+R5VjpnIuTvmfad7IggkUzLZ3Qcz8kuWXLlqLPoEGDTMe3fE7ae6iNS/uc/HUxWwJbk4b2aQFrGv99DRkul074sXZ8/7O0fh7aeVx7Xy2/9ayBs5ler/33wvqd0a5ZrbTjVa5cWdT8YMOkYalxj7XI9LGsLNeB6VxP+7T5aRmXc7ZzvjaGkMGimkyvsT5rIGPIEFHrHPDHpn1mIe9zFMS9s9DBopqk9zgtrN9B7beY9pvE/55Yv7uW85Imne+b/9hMXzNZ5XXe4y/RAQAAAAAAAACIwU10AAAAAAAAAABicBMdAAAAAAAAAIAY5j3Rtf2rNZa9PDO9D3jSPWSte4lp+3hpexQl3Tsp6XuWzh5alv3XtNeddE8z58LuQZX0M09nv96k0vlO+P2sY7Xs7ai9F+nsSWiZUyH3RNfmk2X/aus+dtY9P/N6vjgh9wBL+rlpY7C+7qR7F2tC7uu4adMm03NqtO+Ntve+/7qs+59ahD5fhtzjMOl5Kek+jknXSSvruJLuD6utUZb9RLW5oz3OMv6Qe1VqtXT2brWsgemc8/zXlM5YQ8790GtU0vXTKun+sNrjtP3ITz755Eh7+PDhiceV6e9EXsdOl2X+a+910v1hrVlFFtbriaTXIdY5ZrnGs56zk2ZDJf39Z90n1/qcfk07j4TeE92aOeC/39a95ZPmp1nnSjqfgeU5NUmvd62/Z3wh9zPWhMxU067BLfdq0vm9n/T3bMjrcivLvEjnN0qm90lPup7mx57ovnTOSxbprEeWtT6d70TS+x9Jr/MLIu8vr0w1/hIdAAAAAAAAAIAY3EQHAAAAAAAAACAGN9EBAAAAAAAAAIjBTXQAAAAAAAAAAGLINMwY1kAAP2DTGloSciN4a7BG0gAOLURUC4bywy+soRNJQ0zSCQOwbOpfunTpROOKkzR8wfqeace3fObpBOFZWD8Ty3zRgkCsQQtJw2CsAaSWPtp3Kamkn5F1HbDMC+t3PGmYqfW9TxosmjTsT6uFDlT1a9ZAvXRoa54lxM36vUwaeJ2OpN9VrWY9v1tYvjvphHJZ3n/r55aUdVz+ONIJELME1aUTRBny+CHnkxZ6nvT8nzR00PLZpiudNdtyrKTnDY31OuS9996LtLX3X7t2sF47+0GH2ryzhnBZ1uuQ65Y2hpBzSntfkwbJabSQSf89TPrepzM263fGGjZqOVamA7A1lmvKpL+N42R6TiV9bMjf39b5mfQ3VdLAXO2xoYOnQ/7Oski6FqQTVpjp6yjLGNIJaLc8zvp9S7qeJpXpoHTn9HVdOw9ZzsfW9zHk/VLL+53ONZPGskZZr/NDXsNo74X/nEnvY4nn2uFHAAAAAAAAAABQTHATHQAAAAAAAACAGNxEBwAAAAAAAAAgBjfRAQAAAAAAAACIkZMKmZoFAAAAAAAAAEARwl+iAwAAAAAAAAAQg5voAAAAAAAAAADE4CY6AAAAAAAAAAAxuIkOAAAAAAAAAEAMbqIDAAAAAAAAABCDm+gAAAAAAAAAAMTgJjoAAAAAAAAAADG4iQ4AAAAAAAAAQAxuogMAAAAAAAAAEOP/A9VPzFZL4iVVAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 1500x500 with 30 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化生成结果\n",
    "def visualize_results(generated_images_1rf, generated_images_2rf, real_images, num_samples=10):\n",
    "    \"\"\"可视化生成结果\n",
    "    \n",
    "    Args:\n",
    "        generated_images_1rf: 1-Rectified Flow生成的图像\n",
    "        generated_images_2rf: 2-Rectified Flow生成的图像\n",
    "        real_images: 真实图像\n",
    "        num_samples: 显示的样本数量\n",
    "    \"\"\"\n",
    "    plt.figure(figsize=(15, 5))\n",
    "    \n",
    "    for i in range(num_samples):\n",
    "        # 真实图像\n",
    "        plt.subplot(3, num_samples, i + 1)\n",
    "        plt.imshow(real_images[i][0].numpy(), cmap='gray')\n",
    "        plt.title('真实')\n",
    "        plt.axis('off')\n",
    "        \n",
    "        # 1-Rectified Flow生成图像\n",
    "        plt.subplot(3, num_samples, num_samples + i + 1)\n",
    "        plt.imshow(generated_images_1rf[i][0].numpy(), cmap='gray')\n",
    "        plt.title('1-RF')\n",
    "        plt.axis('off')\n",
    "        \n",
    "        # 2-Rectified Flow生成图像\n",
    "        plt.subplot(3, num_samples, 2 * num_samples + i + 1)\n",
    "        plt.imshow(generated_images_2rf[i][0].numpy(), cmap='gray')\n",
    "        plt.title('2-RF')\n",
    "        plt.axis('off')\n",
    "    \n",
    "    plt.tight_layout()\n",
    "    plt.savefig('./results/comparison.png', dpi=600)\n",
    "    plt.show()\n",
    "\n",
    "# 可视化结果对比\n",
    "visualize_results(generated_images_1rf, generated_images_2rf, real_images, num_samples=10)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "test1",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
